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/.

pierrotlefou
źródło

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/'
Alok Singhal
źródło
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
Vijay
źródło
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

Steven Penny
źródło
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
Melka
źródło
11

Jeśli masz Perla:

perl -pe 's/^/PREFIX/' input.file
Majid Azimi
źródło
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
ghostdog74
źródło
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
navigaid
źródło
„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}
ScriptGuy
źródło
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.

Benjamin W.
źródło
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
Ark25
źródło
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
    
k_vishwanath
źródło
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
Brad Parks
źródło
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.)

Promień
źródło
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