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.