Bagaimana cara mengganti string pada baris ke-5 dari beberapa file teks?

22

Saya ingin mengganti baris ke-5 dari beberapa file teks ( file1.txt, file2.txt, file3.txt, file4.txt ) dengan string "Selamat Pagi" menggunakan perintah terminal tunggal.

Semua file teks terletak di file saya ~/Desktop.

Catatan: Desktop saya terdiri dari 6 file .txt. Saya ingin menerapkan perubahan hanya pada 4 file teks yang disebutkan di atas.

Avinash Raj
sumber

Jawaban:

40

Berikut ini beberapa pendekatan. Saya menggunakan brace expansion ( file{1..4}.txt) yang artinyafile1.txt file2.txt file3.txt file4.txt

  1. Perl

    perl -i -pe 's/.*/ Good Morning / if $.==5' file{1..4}.txt

    Penjelasan:

    • -i: menyebabkan perlmengedit file di tempat, mengubah file asli.

      Jika -idiikuti dengan akhiran ekstensi file, maka cadangan dibuat untuk setiap file yang dimodifikasi. Mis: -i.bakmembuat file1.txt.bakif file1.txtdimodifikasi selama eksekusi.

    • -p: berarti membaca file input baris demi baris, menerapkan skrip dan mencetaknya.

    • -e: memungkinkan Anda untuk melewatkan skrip dari baris perintah.

    • s/.*/ Good Morning /: Itu akan menggantikan teks pada baris saat ini ( .*) dengan Selamat Pagi.

    • $.adalah variabel Perl khusus yang menyimpan nomor baris saat ini dari file input. Jadi,, s/foo/bar/ if $.==5ganti hanya foodengan bardi baris ke-5.

  2. sed

    sed -i '5s/.*/ Good Morning /' file{1..4}.txt

    Penjelasan:

    • -i: Seperti untuk perl, edit file di tempat.

    Secara default, sedmencetak setiap baris file input. The 5s/pattern/replacement/Pola sarana pengganti dengan penggantian pada baris ke-5.

  3. Awk

    for f in file{1..4}.txt; do 
        awk 'NR==5{$0=" Good Morning "}1;' "$f" > foobar && mv foobar "$f"; 
    done

    Penjelasan:

    awktidak memiliki padanan dengan -iopsi¹ yang berarti bahwa kita perlu membuat file sementara ( foobar) yang kemudian diganti namanya untuk menimpa yang asli. Bash loop for f in file{1..4}.txt; do ... ; donehanya melewati masing-masing file{1..4}.txt, menyimpan nama file saat ini sebagai $f. In awk, NRadalah nomor baris saat ini dan $0konten dari baris saat ini. Jadi, skrip akan mengganti baris ( $0) dengan "Selamat Pagi" hanya pada baris ke-5. 1;adalah awkuntuk "mencetak baris".

    ¹ Versi yang lebih baru jangan seperti devnull menunjukkan dalam bukunya jawaban .

  4. coreutils

    for f in file{1..4}.txt; do 
        (head -4 "$f"; echo " Good Morning "; tail -n +6 "$f") > foobar && 
        mv foobar "$f"; 
    done 

    Penjelasan:

    Pengulangan dijelaskan di bagian sebelumnya.

    • head -4: cetak 4 baris pertama

    • echo " Good Morning ": print "Selamat Pagi"

    • tail -n +6: cetak semuanya dari baris ke-6 hingga akhir file

    Tanda kurung di ( )sekitar ketiga perintah memungkinkan Anda untuk menangkap output dari ketiga (jadi, 1 baris 4, lalu "Selamat pagi", lalu sisa baris) dan mengarahkan mereka ke file.

terdon
sumber
23

Anda bisa menggunakan sed:

sed '5s/^/Good morning /' file

akan ditambahkan Good morningpada baris kelima file.

Jika Anda ingin mengganti konten pada baris 5, katakan:

sed '5s/.*/Good morning/' file

Jika Anda ingin menyimpan perubahan ke file di tempat, gunakan -iopsi:

sed -i '5s/.*/Good morning/' file

seddapat menangani lebih dari satu file sekaligus. Anda bisa menambahkan lebih banyak nama file ke akhir perintah. Anda juga dapat menggunakan ekspansi bash untuk mencocokkan file tertentu:

# manually specified
sed -i '5s/.*/Good morning/' file1.txt file2.txt file3.txt file4.txt

# wildcard: all files on the desktop
sed -i '5s/.*/Good morning/' ~/Desktop/*

# brace expansion: file1.txt, file2.txt, file3.txt, file4.txt
sed -i '5s/.*/Good morning/' file{1..4}.txt

Anda dapat membaca lebih lanjut tentang ekspansi brace di sini .


GNU awk versi 4.1.0 dan yang lebih tinggi hadir dengan ekstensi yang memungkinkan pengeditan di tempat. Jadi bisa dibilang:

gawk -i inplace 'NR==5{$0="Good morning"}7' file

untuk mengganti baris # 5 dalam file dengan Good morning!

devnull
sumber
2

Saya tidak melihat solusi python jadi ini dia:

import sys
import os
def open_and_replace(filename):

    with open(filename) as read_file:
        temp = open("/tmp/temp.txt","w")
        for index,line in enumerate(read_file,1):
            if  index == 5:
                temp.write("NEW STRING\n")
            else:
                temp.write(line.strip() + "\n")
        temp.close()
    os.rename("/tmp/temp.txt",filename)

for file_name in sys.argv[1:]:
    open_and_replace(file_name)

Ide dasarnya adalah bahwa untuk setiap file yang disediakan pada baris perintah sebagai argumen, kami menulis file sementara dan menghitung setiap baris dalam file asli. Jika indeks baris adalah 5, kami menulis baris yang berbeda. Sisanya hanya mengganti file lama dengan Demo file temp:

$> ls
file1.txt  file2.txt  file3.txt
$> cat file1.txt                                                               
line 1
line 2
line 3
line 4
GOOD MORNING
line 6
$> python ~/replace_5th_line.py file1.txt file2.txt  file3.txt                 
$> cat file1.txt                                                               
line 1
line 2
line 3
line 4
NEW STRING
line 6
$> cat file2.txt                                                               
line 1
line 2
line 3
line 4
NEW STRING
line 6

Hal yang sama dapat dicapai dengan pemahaman daftar. Di bawah ini adalah satu-baris dari skrip yang sama:

cat /etc/passwd | python -c 'import sys; print "\n".join(["CUSTOM"  if index == 5 else line.strip() for index,line in enumerate(sys.stdin,1)])'

atau tanpa cat

python -c 'import sys; print "\n".join(["CUSTOM"  if index == 5 else line.strip() for index,line in enumerate(sys.stdin,1)])' < /etc/passwd

Apa yang tersisa di sana adalah dengan hanya mengarahkan output dari konten yang diedit ke dalam file lain > output.txt

Sergiy Kolodyazhnyy
sumber
1

Anda dapat menggunakan Vim dalam mode Ex:

for b in 1 2 3 4
do
  ex -sc '5c|Good Morning' -cx file"$b".txt
done
  1. 5 pilih baris ke-5

  2. c ganti teks

  3. x tulis jika ada perubahan (sudah) dan berhenti

Steven Penny
sumber
0

Berikut ini adalah skrip bash yang merangkum proses perl yang disarankan dalam jawaban ini

Contoh:

/ tmp / itu

console:
  enabled:false

Kemudian jalankan yang berikut ini:

$ search_and_replace_on_line_of_file.sh false true 2 /tmp/it

dan file sekarang berisi

/ tmp / itu

console:
  enabled:true

search_and_replace_on_line_of_file.sh

function show_help()
{
  IT=$(CAT <<EOF

  usage: SEARCH REPLACE LINE_NUM FILE

  e.g. 

  false true 52 /tmp/it  -> replaces false with true on line 52 of file /tmp/it

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$4" ]
then
  show_help
fi

SEARCH_FOR=$1
REPLACE_WITH=$2
LINE_NO=$3
FILE_NAME=$4
perl -i -pe "s/$SEARCH_FOR/$REPLACE_WITH/ if $.==$LINE_NO" $FILE_NAME 
taman brad
sumber