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ę.
prefix
będzie zawierać /
. Na przykład jest to ścieżka /opt/workdir/
.
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ę.
prefix
będzie zawierać /
. Na przykład jest to ścieżka /opt/workdir/
.
Odpowiedzi:
# 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 prefix
zawiera /
, możesz użyć dowolnego innego znaku, którego nie ma prefix
, lub uciec przed nim /
, aby sed
polecenie stało się
's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'
sed
z potoku, np foo | sed -e 's/^/x /' | bar
.
sed -e '2,$s/^/prefix/'
.
sed -e 's/$/postfix/' file
jeśli chcesz dodać ciąg na końcu każdej linii.
awk '$0="prefix"$0' file > new_file
Z Perlem (zamiennik na miejscu):
perl -pi 's/^/prefix/' file
prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
awk
raporty awk: out of memory in readrec 1 source line number 1
, ale rozwiązanie z sed
pomyślnie się kończy.
Możesz używać Vima w trybie Ex:
ex -sc '%s/^/prefix/|x' file
%
wybierz wszystkie linie
s
zastąpić
x
Zapisz i zamknij
:%s/^/prefix/
, ponieważ ta strategia przydaje się w wielu sytuacjach
Jeśli masz Perla:
perl -pe 's/^/PREFIX/' input.file
Za pomocą powłoki:
#!/bin/bash
prefix="something"
file="file"
while read -r line
do
echo "${prefix}$line"
done <$file > newfile
mv newfile $file
Oto wysoce czytelne rozwiązanie oneliner, wykorzystujące ts
polecenie 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
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 -s
opcji, nl
był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}
-u
opcji sed, aby uniknąć buforowania.
Za pomocą ed:
ed infile <<'EOE'
,s/^/prefix/
wq
EOE
To zastępuje, dla każdej linii ( ,
), początek linii ( ^
) znakiem prefix
. wq
zapisuje i wychodzi.
Jeśli ciąg zastępujący zawiera ukośnik, s
zamiast 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.
Możesz to również osiągnąć za pomocą techniki odsyłania wstecznego
sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
Możesz także używać z awk w ten sposób
awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
Oto zawarty przykład z wykorzystaniem sed
podejścia z tej odpowiedzi :
$ cat /path/to/some/file | prefix_lines "WOW: "
WOW: some text
WOW: another line
WOW: more text
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
PREFIX
zawiera jakieś znaki specjalne do sedowania jak ukośnik.
prefix_lines \*
Dla osób korzystających z systemów BSD / OSX istnieje narzędzie zwane lam
skrótem do laminatu. lam -s prefix file
zrobi 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.)
sed
takie lekkie zadania. Jeśli znany jest „prefiks”, bardzo łatwo jest wybrać znak nie z „prefiksu”.