Làm cách nào để thay thế một chuỗi trên dòng thứ 5 của nhiều tệp văn bản?


22

Tôi muốn thay thế dòng thứ 5 của nhiều tệp văn bản ( file1.txt, file2.txt, file3.txt, file4.txt ) bằng chuỗi "Chào buổi sáng" bằng một lệnh đầu cuối.

Tất cả các tập tin văn bản được đặt trên của tôi ~/Desktop.

Lưu ý: Máy tính để bàn của tôi bao gồm 6 tệp .txt. Tôi chỉ muốn áp dụng thay đổi cho 4 tệp văn bản đã đề cập ở trên.

Câu trả lời:


40

Dưới đây là một vài cách tiếp cận. Tôi đang sử dụng niềng răng mở rộng ( file{1..4}.txt) có nghĩa làfile1.txt file2.txt file3.txt file4.txt

  1. Perl

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

    Giải trình:

    • -i: nguyên nhân perlđể chỉnh sửa các tệp tại chỗ, thay đổi tệp gốc.

      Nếu -iđược theo sau với hậu tố mở rộng tệp, thì bản sao lưu được tạo cho mọi tệp được sửa đổi. Ví dụ: -i.baktạo một file1.txt.bakif file1.txtđược sửa đổi trong khi thực hiện.

    • -p: có nghĩa là đọc từng dòng tệp đầu vào, áp dụng tập lệnh và in nó.

    • -e: cho phép bạn truyền một tập lệnh từ dòng lệnh.

    • s/.*/ Good Morning /: Điều đó sẽ thay thế văn bản trong dòng hiện tại ( .*) bằng Chào buổi sáng.

    • $.là một biến Perl đặc biệt chứa số dòng hiện tại của tệp đầu vào. Vì vậy, s/foo/bar/ if $.==5phương tiện thay thế foovới barchỉ trên dòng thứ 5.

  2. quyến rũ

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

    Giải trình:

    • -i: Thích cho perl, chỉnh sửa tập tin tại chỗ.

    Theo mặc định, sedin từng dòng của tệp đầu vào. Các 5s/pattern/replacement/mẫu có nghĩa là thay thế với thay thế trên dòng thứ 5.

  3. Awk

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

    Giải trình:

    awkkhông có tương đương với -itùy chọn - có nghĩa là chúng ta cần tạo một tệp tạm thời ( foobar) sau đó được đổi tên để ghi đè lên bản gốc. Vòng lặp bash for f in file{1..4}.txt; do ... ; donechỉ đơn giản là đi qua từng cái file{1..4}.txt, lưu tên tệp hiện tại là $f. Trong awk, NRlà số dòng hiện tại và $0là nội dung của dòng hiện tại. Vì vậy, tập lệnh sẽ thay thế dòng ( $0) bằng "Chào buổi sáng" chỉ trên dòng thứ 5. 1;awkcho "in dòng".

    ¹ Phiên bản mới hơn làm như devnull cho thấy trong mình câu trả lời .

  4. lõi

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

    Giải trình:

    Vòng lặp được giải thích trong phần trước.

    • head -4: in 4 dòng đầu tiên

    • echo " Good Morning ": in "Chào buổi sáng"

    • tail -n +6: in mọi thứ từ dòng thứ 6 đến cuối tập tin

    Các dấu ngoặc đơn ( )xung quanh ba lệnh đó cho phép bạn nắm bắt đầu ra của cả ba (vì vậy, 4 dòng đầu tiên, sau đó là "Chào buổi sáng", sau đó là các dòng còn lại) và chuyển hướng chúng đến một tệp.


23

Bạn có thể sử dụng sed:

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

sẽ nối Good morningvào dòng thứ năm của một tập tin.

Nếu bạn muốn thay thế nội dung trên dòng 5 thay vào đó, hãy nói:

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

Nếu bạn muốn lưu các thay đổi vào tệp tại chỗ, hãy sử dụng -itùy chọn:

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

sedcó thể xử lý nhiều tệp cùng một lúc. Bạn chỉ có thể thêm nhiều tên tệp vào cuối lệnh. Bạn cũng có thể sử dụng mở rộng bash để khớp với các tệp cụ thể:

# 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

Bạn có thể đọc thêm về mở rộng cú đúp ở đây .


GNU awk phiên bản 4.1.0 trở lên đi kèm với một phần mở rộng cho phép chỉnh sửa tại chỗ. Vì vậy, bạn có thể nói:

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

để thay thế dòng số 5 trong tệp bằng Good morning!


2

Tôi không thấy giải pháp python nên đây là:

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)

Ý tưởng cơ bản là đối với mỗi tệp được cung cấp trên dòng lệnh làm đối số, chúng tôi viết ra một tệp tạm thời và liệt kê từng dòng trong tệp gốc. Nếu chỉ số của dòng là 5, chúng tôi viết ra dòng khác nhau. Phần còn lại chỉ là thay thế tệp cũ bằng tệp tạm thời Demo:

$> 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

Điều tương tự có thể đạt được với sự hiểu biết danh sách. Dưới đây là một lớp lót của cùng một kịch bản:

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)])'

hoặc không có 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

Những gì còn lại chỉ đơn giản là chuyển hướng đầu ra của nội dung được chỉnh sửa sang một tệp khác với > output.txt


1

Bạn có thể sử dụng Vim trong chế độ Ex:

for b in 1 2 3 4
do
  ex -sc '5c|Good Morning' -cx file"$b".txt
done
  1. 5 chọn dòng thứ 5

  2. c thay thế văn bản

  3. x viết nếu thay đổi đã được thực hiện (họ có) và thoát


0

Sau đây là tập lệnh bash kết thúc quá trình perl được đề xuất trong câu trả lời này

Thí dụ:

/ tmp / nó

console:
  enabled:false

Sau đó chạy như sau:

$ search_and_replace_on_line_of_file.sh false true 2 /tmp/it

và tập tin hiện chứa

/ tmp / nó

console:
  enabled:true

tìm kiếm_and numplace_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 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.