Tambahkan string awalan ke awal setiap baris


334

Saya punya file seperti di bawah ini:

line1
line2
line3

Dan saya ingin mendapatkan:

prefixline1
prefixline2
prefixline3

Saya bisa menulis skrip Ruby, tetapi lebih baik jika saya tidak perlu.

prefixakan mengandung /. Itu adalah jalan, /opt/workdir/misalnya.

Jawaban:


527
# 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

Jika prefixmengandung /, Anda dapat menggunakan karakter lain yang tidak ada di dalam prefix, atau keluar dari /, sehingga sedperintah menjadi

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

1
@ Benjamin, saya sudah meningkatkan jawaban Anda, namun, saya lebih suka seduntuk tugas-tugas ringan seperti ini. Jika "awalan" diketahui, sangat mudah untuk memilih karakter bukan dari "awalan".
Alok Singhal

1
Jangan lupa, Anda juga dapat menggunakan sedpipa, misalnya foo | sed -e 's/^/x /' | bar.
zigg

1
@Dataman keren. Cara lain adalah sed -e '2,$s/^/prefix/'.
Alok Singhal

1
@BinChen lolos dari /like \/(dalam string yang dikutip tunggal) atau \\/(dalam string yang dikutip ganda)

8
Gunakan sed -e 's/$/postfix/' filejika Anda ingin menambahkan string ke akhir setiap baris.
Brian

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

Dengan Perl (pengganti di tempat):

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

8
Dengan pipa / aliran atau variabel:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner

2
Dengan file besar (12 G), awklaporan awk: out of memory in readrec 1 source line number 1, tetapi solusi dengan sedberhasil selesai.
jrm

33

Anda dapat menggunakan Vim dalam mode Ex:

ex -sc '%s/^/prefix/|x' file
  1. % pilih semua baris

  2. s menggantikan

  3. x Simpan dan tutup


1
Bagi saya, saya baru saja membuka file dalam vim dan ketik :%s/^/prefix/, karena strategi ini akhirnya berguna dalam banyak situasi
Frank Bryce

23

Jika awalan Anda sedikit rumit, masukkan saja dalam variabel:

prefix=path/to/file/

Kemudian, Anda meneruskan variabel itu dan membiarkan awk menanganinya:

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


6

Menggunakan shell:

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

5

Berikut ini adalah solusi oneliner yang dapat dibaca dengan baik menggunakan tsperintah dari moreutils

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

Dan bagaimana itu diturunkan langkah demi langkah:

# 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' tidak diinstal secara default di banyak distro Linux. Juga, downvoting karena jejak "tr -d ''" dalam jawaban ini akan menghapus semua spasi dari garis, bukan hanya ruang yang ditambahkan oleh 'ts'
Tim Bird

3

Meskipun saya tidak berpikir pierr memiliki masalah ini, saya membutuhkan solusi yang tidak akan menunda output dari "ekor" file, karena saya ingin memonitor beberapa log peringatan secara bersamaan, mengawali setiap baris dengan nama masing-masing log .

Sayangnya, sed, cut, dll. Memperkenalkan terlalu banyak buffering dan membuat saya tidak bisa melihat baris terbaru. Saran Steven Penny untuk menggunakan -sopsi nlmenarik, dan pengujian membuktikan bahwa itu tidak memperkenalkan buffer yang tidak diinginkan yang membuat saya khawatir.

Namun, ada beberapa masalah dengan penggunaan nl, terkait dengan keinginan untuk menghapus nomor baris yang tidak diinginkan (bahkan jika Anda tidak peduli dengan estetika itu, mungkin ada kasus di mana menggunakan kolom tambahan tidak diinginkan). Pertama, menggunakan "potong" untuk menghapus angka-angka yang memperkenalkan kembali masalah buffering, sehingga merusak solusi. Kedua, menggunakan "-w1" tidak membantu, karena ini TIDAK membatasi jumlah baris menjadi satu kolom - itu hanya menjadi lebih luas karena lebih banyak digit diperlukan.

Tidak cantik jika Anda ingin mengambil ini di tempat lain, tetapi karena itulah yang sebenarnya tidak perlu saya lakukan (semuanya sudah ditulis untuk mencatat file, saya hanya ingin menonton beberapa sekaligus dalam waktu nyata), yang terbaik cara untuk kehilangan nomor baris dan hanya awalan saya adalah memulai -sstring dengan carriage return (CR atau ^ M atau Ctrl-M). Jadi misalnya:

#!/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
gunakan -uopsi sed untuk menghindari buffering.
Bryan Larsen

2
Buffering dapat dimatikan dengan unbuffer / stdbuf, lihat unix.stackexchange.com/q/25372/6205
myroslav

2

Menggunakan ed:

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

Ini menggantikan, untuk setiap baris ( ,), awal baris ( ^) dengan prefix. wqmenyimpan dan keluar.

Jika string pengganti berisi garis miring, kita dapat menggunakan pembatas yang berbeda untuk s:

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

Saya telah mengutip pembatas di sini-doc EOE("ujung ed") untuk mencegah ekspansi parameter. Dalam contoh ini, ini akan bekerja tanpa tanda kutip juga, tetapi praktik yang baik untuk mencegah kejutan jika Anda pernah memiliki $dalam skrip ed Anda.


2

Menggunakan & (seluruh bagian dari input yang cocok dengan pola ”):

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

ATAU menggunakan referensi balik:

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

2
  1. Anda juga dapat mencapai ini menggunakan teknik backreference

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Anda juga bisa menggunakannya dengan awk seperti ini

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

1

Berikut ini adalah contoh terbungkus menggunakan sedpendekatan dari jawaban ini :

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

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

prefix_lines

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
Ini tidak akan berfungsi jika PREFIXberisi karakter khusus untuk sed seperti garis miring.
josch

Poin bagus ... Jika Anda menggunakan slash alot, Anda bisa menggunakan pembatas yang berbeda dengan bagian sed, seperti yang dijelaskan di sini , yang akan memungkinkan Anda untuk menggunakannya dalam pencarian. Karakter sed khusus lainnya dapat dimasukkan dengan melarikan diri dengan tebasan, misalnyaprefix_lines \*
Brad Parks

0

Untuk orang-orang di sistem BSD / OSX ada utilitas bernama lam, kependekan dari laminasi. lam -s prefix fileakan melakukan apa yang Anda inginkan. Saya menggunakannya di jalur pipa, misalnya:

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

... yang akan menemukan semua file, terutama pada masing-masing, memberikan setiap file awalan dari nama file sendiri. (Dan pompa output ke fzf untuk pencarian.)


Anda benar, sepertinya ini hanya perintah BSD. POSIX menggantinya dengan pasta, tetapi tempel tidak memiliki fitur menambahkan string pemisah penuh. Saya akan memperbarui jawaban saya.
Ray
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.