Dodaj ciąg prefiksu na początku każdej linii


334

Mam plik jak poniżej:

line1
line2
line3

I chcę uzyskać:

prefixline1
prefixline2
prefixline3

Mógłbym napisać skrypt Ruby, ale lepiej, jeśli nie muszę.

prefixbędzie zawierać /. Na przykład jest to ścieżka /opt/workdir/.

Odpowiedzi:


526
# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file

# If you want to create a new file
sed -e 's/^/prefix/' file > file.new

Jeśli prefixzawiera /, możesz użyć dowolnego innego znaku, którego nie ma prefix, lub uciec przed nim /, aby sedpolecenie stało się

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'

1
@benjamin, głosowałem już za twoją odpowiedzią, jednak wolę sedtakie lekkie zadania. Jeśli znany jest „prefiks”, bardzo łatwo jest wybrać znak nie z „prefiksu”.
— Alok Singhal

1
Nie zapominaj, że możesz również korzystać sedz potoku, np foo | sed -e 's/^/x /' | bar.
— zigg

1
@Dataman cool. Innym sposobem byłoby sed -e '2,$s/^/prefix/'.
— Alok Singhal

1
@BinChen uciec /jak \/(w ciągach pojedynczych) lub \\/(w ciągach podwójnych)

8
Użyj, sed -e 's/$/postfix/' filejeśli chcesz dodać ciąg na końcu każdej linii.
— Brian

121
awk '$0="prefix"$0' file > new_file

Z Perlem (zamiennik na miejscu):

perl -pi 's/^/prefix/' file

8
Z potokiem / strumieniem lub zmienną:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
— ThorSummoner

2
Z dużym plikiem (12 G), awkraporty awk: out of memory in readrec 1 source line number 1, ale rozwiązanie z sedpomyślnie się kończy.
— jrm

33

Możesz używać Vima w trybie Ex:

ex -sc '%s/^/prefix/|x' file
  1. % wybierz wszystkie linie

  2. s zastąpić

  3. x Zapisz i zamknij


1
Dla mnie po prostu otwieram plik w vimie i piszę :%s/^/prefix/, ponieważ ta strategia przydaje się w wielu sytuacjach
— Frank Bryce

23

Jeśli twój prefiks jest nieco skomplikowany, po prostu umieść go w zmiennej:

prefix=path/to/file/

Następnie przekazujesz tę zmienną i pozwalasz awk sobie z tym poradzić:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt


6

Za pomocą powłoki:

#!/bin/bash
prefix="something"
file="file"
while read -r line
do
 echo "${prefix}$line"
done <$file > newfile
mv newfile $file

5

Oto wysoce czytelne rozwiązanie oneliner, wykorzystujące tspolecenie z moreutils

$ cat file | ts prefix | tr -d ' '

I w jaki sposób jest uzyskiwany krok po kroku:

# Step 0. create the file

$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line

$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle

$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3

„ts” nie jest instalowane domyślnie na wielu dystrybucjach Linuksa. Również głosowanie w dół, ponieważ końcowe „tr -d” w tej odpowiedzi usunie wszystkie spacje z linii, a nie tylko spację dodaną przez „ts”
— Tim Bird

3

Chociaż nie sądzę, by Pierr miał takie obawy, potrzebowałem rozwiązania, które nie opóźniałoby wyjścia z „ogona” pliku na żywo, ponieważ chciałem monitorować kilka dzienników alertów jednocześnie, poprzedzając każdą linię nazwą odpowiedniego dziennika .

Niestety, sed, cut itp. Wprowadziły za dużo buforowania i powstrzymały mnie od oglądania najnowszych linii. Sugestia Stevena Penny'ego, aby skorzystać z -sopcji, nlbyła intrygująca, a testy wykazały, że nie wprowadziło to niechcianego buforowania, które mnie dotyczyło.

Było jednak kilka problemów związanych z używaniem nl, związanych z chęcią usunięcia niechcianych numerów linii (nawet jeśli nie zależy ci na estetyce, mogą wystąpić przypadki, w których użycie dodatkowych kolumn byłoby niepożądane). Po pierwsze, użycie „cut” do usunięcia liczb ponownie wprowadza problem buforowania, więc rujnuje rozwiązanie. Po drugie, użycie „-w1” nie pomaga, ponieważ to NIE ogranicza numeru linii do pojedynczej kolumny - po prostu poszerza się, ponieważ potrzeba więcej cyfr.

To nie jest ładne, jeśli chcesz uchwycić to gdzie indziej, ale ponieważ dokładnie tego nie musiałem robić (wszystko było już zapisane w plikach dziennika, chciałem tylko oglądać kilka naraz w czasie rzeczywistym), najlepiej sposobem na utratę numerów linii i posiadanie tylko mojego prefiksu było rozpoczęcie -słańcucha od znaku powrotu karetki (CR lub ^ M lub Ctrl-M). Na przykład:

#!/bin/ksh

# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.

PGRP=$$

for LOGFILE in widget framas dweezil
do
(
    tail -f $LOGFILE 2>&1 |
    nl -s"^M${LOGFILE}>  "
) &
sleep 1
done

read KILLEM

kill -- -${PGRP}

1
użyj -uopcji sed, aby uniknąć buforowania.
— Bryan Larsen

2
Buforowanie można wyłączyć za pomocą unbuffer / stdbuf, patrz unix.stackexchange.com/q/25372/6205
— myroslav

2

Za pomocą ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

To zastępuje, dla każdej linii ( ,), początek linii ( ^) znakiem prefix. wqzapisuje i wychodzi.

Jeśli ciąg zastępujący zawiera ukośnik, szamiast tego możemy użyć innego ogranicznika :

ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE

Przytoczyłem ogranicznik tutaj-doc EOE(„koniec edycji”), aby zapobiec rozszerzaniu parametrów. W tym przykładzie działałoby to również bez cudzysłowu, ale dobrą praktyką jest zapobieganie niespodziankom, jeśli kiedykolwiek masz $w swoim skrypcie ed.


2

Używając & (cała część danych wejściowych, która została dopasowana przez wzorzec ”):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

LUB używając referencji:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt

2
  1. Możesz to również osiągnąć za pomocą techniki odsyłania wstecznego

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Możesz także używać z awk w ten sposób

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    

1

Oto zawarty przykład z wykorzystaniem sedpodejścia z tej odpowiedzi :

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

linie_refiksów

function show_help()
{
  IT=$(CAT <<EOF
    Usage: PREFIX {FILE}

    e.g.

    cat /path/to/file | prefix_lines "WOW: "

      WOW: some text
      WOW: another line
      WOW: more text
  )
  echo "$IT"
  exit
}

# Require a prefix
if [ -z "$1" ]
then
  show_help
fi

# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
  # If no stdin exists
  if [ -t 0 ]; then
    show_help
  fi
  FILE=/dev/stdin
fi

# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE

2
To nie zadziała, jeśli PREFIXzawiera jakieś znaki specjalne do sedowania jak ukośnik.
— josch

Dobra uwaga ... Jeśli okaże się, że używasz ukośnika, możesz użyć innego separatora z częścią sed, jak wyszczególniono tutaj , co pozwoliłoby ci używać go podczas wyszukiwania. Inne specjalne znaki sed można wprowadzić, uciekając ukośnikiem, np.prefix_lines \*
— Brad Parks

0

Dla osób korzystających z systemów BSD / OSX istnieje narzędzie zwane lamskrótem do laminatu. lam -s prefix filezrobi co chcesz. Używam go w rurociągach, np .:

find -type f -exec lam -s "{}: " "{}" \; | fzf

... który znajdzie wszystkie pliki, wykonaj polecenie lam na każdym z nich, nadając każdemu plikowi prefiks własnej nazwy pliku. (I przepompuj dane wyjściowe do fzf w celu wyszukiwania.)


Masz rację, wygląda na to, że jest to polecenie tylko BSD. POSIX zastąpił go pastą, ale pasta nie ma funkcji dodawania pełnego ciągu separatora. Zaktualizuję moją odpowiedź.
— Ray
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.