여러 텍스트 파일의 다섯 번째 줄에서 문자열을 바꾸는 방법은 무엇입니까?


22

단일 터미널 명령을 사용하여 여러 텍스트 파일 ( file1.txt, file2.txt, file3.txt, file4.txt ) 의 다섯 번째 줄을 "Good Morning"문자열로 바꾸고 싶습니다 .

모든 텍스트 파일은 내에 있습니다 ~/Desktop.

참고 : 데스크탑은 6 개의 .txt 파일로 구성되어 있습니다. 위에서 언급 한 4 개의 텍스트 파일에만 변경 사항을 적용하고 싶습니다.

답변:


40

몇 가지 접근 방식이 있습니다. 내가 사용하고 중괄호 확장 ( file{1..4}.txt) 수단을file1.txt file2.txt file3.txt file4.txt

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

    설명:

    • -i: perl원본 파일을 변경하고 제자리에서 파일을 편집합니다.

      경우 -i파일 확장자 접미사 다음에, 다음 백업은 수정 된 모든 파일에 대해 생성됩니다. 예는 : -i.bak를 생성 file1.txt.bak하는 경우 file1.txt실행 중에 수정됩니다.

    • -p: 입력 파일을 한 줄씩 읽고 스크립트를 적용하여 인쇄하는 것을 의미합니다.

    • -e: 명령 행에서 스크립트를 전달할 수 있습니다.

    • s/.*/ Good Morning /: 현재 줄 ( .*) 의 텍스트 가 Good Morning으로 바뀝니다.

    • $.입력 파일의 현재 행 번호를 보유하는 특수 Perl 변수입니다. 그래서 s/foo/bar/ if $.==5, 수단 대신 foobar단지 5 라인.

  2. sed

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

    설명:

    • -i: 에서처럼 perl파일을 편집합니다.

    기본적으로 sed입력 파일의 각 줄을 인쇄합니다. 5s/pattern/replacement/5 라인 교체와 수단의 대체 패턴.

  3. 어 wk

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

    설명:

    awk-i옵션 ¹에 해당하지 않습니다. 즉, 임시 파일 ( foobar)을 만든 다음 원본을 덮어 쓰기 위해 이름을 바꿉니다 . bash 루프는 for f in file{1..4}.txt; do ... ; done단순히 각 file{1..4}.txt파일을 통과 하여 현재 파일 이름을로 저장합니다 $f. 에서는 awk, NR현재 행 번호와 $0현재 줄의 내용입니다. 따라서 스크립트는 $05 번째 줄에서만 줄 ( )을 "Good Morning"으로 바꿉니다. 1;이다 awk"선을 인쇄"를 참조하십시오.

    ¹ 새로운 버전은 devnull이 그의 답변 에서 보여준 것처럼 작동 합니다.

  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 

    설명:

    루프는 이전 섹션에서 설명되었습니다.

    • head -4: 첫 4 행 인쇄

    • echo " Good Morning ": "Good Morning"인쇄

    • tail -n +6: 6 번째 줄부터 파일 끝까지 모든 것을 인쇄

    ( )세 명령 주위 의 괄호 를 사용하면 세 개의 출력 (첫 번째 4 행, "좋은 아침", 나머지 행)을 모두 캡처하여 파일로 리디렉션 할 수 있습니다.


23

당신은 사용할 수 있습니다 sed:

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

Good morning파일의 다섯 번째 줄에 추가 합니다.

대신 5 행의 내용을 바꾸려면 다음과 같이 말합니다.

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

파일의 변경 사항을 제자리에 저장하려면 다음 -i옵션을 사용하십시오 .

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

sed한 번에 둘 이상의 파일을 처리 할 수 ​​있습니다. 명령 끝에 파일 이름을 더 추가 할 수 있습니다. bash 확장을 사용하여 특정 파일과 일치시킬 수도 있습니다.

# 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

당신은 여기 중괄호 확장에 대한 자세한 내용을보실 수 있습니다 .


GNU awk 버전 4.1.0 이상 에는 내부 편집이 가능한 확장 기능 이 포함되어 있습니다. 그래서 당신은 말할 수 있습니다 :

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

파일의 5 번 라인을 Good morning!


2

파이썬 솔루션을 보지 못했기 때문에 여기에 있습니다.

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)

기본 아이디어는 명령 줄에 인수로 제공된 각 파일에 대해 임시 파일을 작성하고 각 파일을 원본 파일에 열거한다는 것입니다. 행의 인덱스가 5이면 다른 행을 써냅니다. 나머지는 오래된 파일을 임시 파일 데모로 바꾸는 것입니다.

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

리스트 이해도 마찬가지입니다. 아래는 동일한 스크립트의 한 줄짜리입니다.

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

또는없이 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

남은 것은 단순히 편집 된 내용의 출력을 다른 파일로 리디렉션하는 것입니다. > output.txt


1

Ex 모드에서 Vim을 사용할 수 있습니다 :

for b in 1 2 3 4
do
  ex -sc '5c|Good Morning' -cx file"$b".txt
done
  1. 5 다섯 번째 줄을 선택하십시오

  2. c 텍스트를 교체

  3. x 변경 사항이 있으면 작성하고 종료하십시오.


0

다음은 이 답변에서 제안 된 펄 프로세스 를 마무리하는 bash 스크립트입니다

예:

/ tmp / it

console:
  enabled:false

그런 다음 다음을 실행하십시오.

$ search_and_replace_on_line_of_file.sh false true 2 /tmp/it

그리고 파일은 이제

/ tmp / it

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 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.