W Bash, jak dodać ciąg po każdym wierszu w pliku?

112

Jak dodać ciąg po każdej linii w pliku za pomocą bash? Czy można to zrobić za pomocą polecenia sed, a jeśli tak, to w jaki sposób?

Jason Volkoz
źródło

Odpowiedzi:

188

Jeśli sedzezwala się na edycję w miejscu za pomocą -iparametru:

sed -e 's/$/string after each line/' -i filename

Jeśli nie, musisz utworzyć plik tymczasowy:

typeset TMP_FILE=$( mktemp )

touch "${TMP_FILE}"
cp -p filename "${TMP_FILE}"
sed -e 's/$/string after each line/' "${TMP_FILE}" > filename
Tom DeGisi
źródło
Dlaczego masz touchplik tymczasowy? I uzależniłbym to sedpolecenie od sukcesu cpalbo oryginał mógłby zostać utracony.
Wstrzymano do odwołania.
Dotknąłem pliku, aby szybko zarezerwować tymczasową nazwę. To może nie być potrzebne. Myślę, że masz rację, uzależniając polecenie sed od powodzenia cp. Dlaczego by nie edytować kodu, aby to naprawić. Nie mam nic przeciwko! Pozdrawiam, Tom
Tom DeGisi
A co z dodaniem ciągu znaków przed linią?
Oxwivi
10
@Oxwivi: sed -e 's/^/string after each line/' -i filename $ oznacza koniec linii. ^ oznacza początek wiersza.
Tom DeGisi
Jeśli podłączam do seda, sed 's/^/string after each line/'robi to, czego się spodziewałem (dołącza do każdej linii), ale sed 's/^/string after each line/'nie (zastępuje całą linię moim ciągiem dołączania). Co daje? Jakieś pomysły @TomDeGisi?
philadams
17

Wolę używać awk. Jeśli jest tylko jedna kolumna, użyj $0, w przeciwnym razie zastąp ją ostatnią kolumną.

Jednokierunkowa,

awk '{print $0, "string to append after each line"}' file > new_file

albo to,

awk '$0=$0"string to append after each line"' file > new_file
Optimus Prime
źródło
1
Ponadto, aby dodać numery wierszy (tak jak było w moim przypadku), można użyć NRzmiennej:awk '{print $0, NR}'
andrybak
2
@optimus Wypróbowałem twoją metodę, ale masz dla nich dodatkowe miejsce, masz pomysł, jak je usunąć?
Adil Saju
@AdilSaju sed 's/ //g'to działało zgodnie z moim wymaganiem, ale usunie spację w każdej linii, to jest opcja gdla i wszędzie w linii.
Eklavyaa
@AdilSaju dodaj szczegóły. Lepiej zadać nowe pytanie.
Optimus Prime
@AdilSaju awk Usunąć , jak {print $0"string to append after each line"}.
Culip
8

Jeśli go masz, narzędzie lam (laminat) może to zrobić, na przykład:

$ lam filename -s "string after each line"
Martin Clayton
źródło
4
  1. Czysta powłoka POSIX i sponge:

    suffix=foobar
    while read l ; do printf '%s\n' "$l" "${suffix}" ; done < file | 
    sponge file
  2. xargsi printf:

    suffix=foobar
    xargs -L 1 printf "%s${suffix}\n" < file | sponge file
  3. Używając join:

    suffix=foobar
    join file file -e "${suffix}" -o 1.1,2.99999 | sponge file
  4. Narzędzia Shell za pomocą paste, yes, head i wc:

    suffix=foobar
    paste file <(yes "${suffix}" | head -$(wc -l < file) ) | sponge file

    Zauważ, że pastewstawia znak Tab przed $suffix.

Oczywiście spongemożna go zastąpić plikiem tymczasowym, a następnie mvnad oryginalną nazwą pliku, tak jak w przypadku niektórych innych odpowiedzi ...

agc
źródło
1
Żaden z nich nie jest lepszy sed, chyba że zasoby są bardzo ograniczone.
agc,
Podoba mi się rozwiązanie non-sed. sednie jest potrzebny do tak prostej pracy.
Bruce
1

Wolę echo. używając czystego basha:

cat file | while read line; do echo ${line}$string; done
欢乐 的 Xiaox
źródło
-9

Sed jest trochę brzydki, możesz to zrobić elegancko w ten sposób:

hendry@i7 tmp$ cat foo 
bar
candy
car
hendry@i7 tmp$ for i in `cat foo`; do echo ${i}bar; done
barbar
candybar
carbar
hendry
źródło
2
Niepowodzenie dla plików zawierających więcej wierszy niż maksymalny limit argumentów powłoki. Spróbuj: cat foo | podczas czytania; do echo $ {a} bar; zrobione lub coś w tym stylu; jest to odpowiedni zamiennik w większości przypadków.
alex
1
Zawodzi również w przypadku wierszy zawierających spacje.
Wstrzymano do odwołania.
1
Eee, nie, to nie zawodzi Dennisa. maksymalny limit argumentów powłoki? Crikey, jesteś pendantyczny.
hendry
Tak: $ cat foo foo bar baz alex @ armitage: ~ $ for i in cat foo; do echo $ {i} bar; zrobione foobar barbar bazbar ale po kilku testach mogę się mylić co do mojego rozumowania, ale Dennis ma rację
alex
3
@hendry Tak, nie udaje się to w przypadku wierszy zawierających spacje, na przykład w przypadku echo "foo bar" | (for i in `cat`; do echo ${i}bar; done)drukowania 2 wierszy, mimo że wejście to 1 wiersz foo bar(a catodczyt ze standardowego wejścia zamiast z pliku nie ma w tym żadnego znaczenia).
hyde