텍스트 파일의 전체 줄을 줄 번호로 바꾸는 방법


152

bash 스크립트가 파일의 전체 줄을 바꾸려는 상황이 있습니다. 줄 번호는 항상 동일하므로 하드 코딩 된 변수가 될 수 있습니다.

해당 줄의 일부 하위 문자열을 바꾸려고하지 않고 해당 줄을 완전히 새 줄로 바꿉니다.

이 작업을 수행하는 bash 메서드가 있습니까 (또는 .sh 스크립트에 던져 질 수있는 간단한 방법).

답변:


228

가장 크지는 않지만 작동해야합니다.

sed -i 'Ns/.*/replacement-line/' file.txt

여기서 N대상 행 번호로 대체해야합니다. 원본 파일의 줄이 바뀝니다. 변경된 텍스트를 다른 파일에 저장하려면 -i옵션을 삭제하십시오 .

sed 'Ns/.*/replacement-line/' file.txt > new_file.txt

1
화면에 덤프하는 대신 sed가 문제의 파일을 수정하도록하는 방법이 있습니까?
user788171 2016 년

8
나에게 그것은 말한다 : sed: -e expression #1, char 26: unknown option to ``s'그리고 내 라인은 : sed -i '7s/.*/<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>/' $TCE_SVN_HOME\trunk\tce\EWC\WebContent\WEB-INF\web.xml. 어떤 생각?
Danijel

4
/대체 텍스트의 각 항목 은 s이스케이프 처리되지 않는 한 명령 의 닫는 슬래시로 해석됩니다 ( \/). 그러나 가장 쉬운 방법은 다른 사용되지 않는 문자를 구분 기호로 선택하는 것입니다. 예를 들면 다음과 같습니다 sed -i '7s{.*}{<param-value>http://...}' $TCE_SVN_HOME/trunk....
chepner

4
그 설명은 약간 혼란스럽고 작동하지 않는 것 같습니다. sed 및 구분 기호 설정 기능에 문제가있는 경우 grymoire.com/Unix/Sed.html#uh-2를 살펴보십시오 s. 뒤에있는 첫 번째 문자 가 구분 기호를 결정합니다. 예를 들어 사용하도록 명령을 변경하려면 다음 #과 같이하십시오.sed -i '7s#.*#<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpo‌​int/</param-value>#'
func0der

7
@meonlol을 확장하기 위해 macOS에는 -eif -i도 제공 해야합니다 . 따라서 올바른 명령은 다음과 같습니다.sed -e 'Ns/.*/replacement-line/' -i '' file.txt
ELLIOTTCABLE

44

실제로이 스크립트를 사용하여 회사 UNIX 서버의 cron 파일에있는 코드 줄을 한 번에 바꿨습니다. 우리는 일반적인 쉘 스크립트로 실행했으며 아무런 문제가 없었습니다.

#Create temporary file with new line in place
cat /dir/file | sed -e "s/the_original_line/the_new_line/" > /dir/temp_file
#Copy the new file over the original file
mv /dir/temp_file /dir/file

이것은 행 번호를 기준으로하지 않지만 행 번호 앞에 s/와 번호를 배치하여 행 번호 기반 시스템으로 쉽게 전환 할 수 있습니다 the_original_line.


17
고양이의 쓸모없는 사용 :sed -e "s/.../.../" /dir/file > /dir/temp_file
chepner

24
통역사 / 컴파일러에게는 쓸모가 없지만 사람이 읽을 수는 없습니다. @Kyle의 코드는 왼쪽에서 오른쪽으로 잘 읽습니다. 동사가 명사 앞에 있다는 사실 때문에 IMO를 사용한 관용구는 그렇지 않습니다.
Clayton Stanley

1
예를 들어 다음과 같이 두 줄을 병합하는 방법이 있습니까?sed -e "s/.../.../" /dir/file > /dir/file
Pubudu Dodangoda

22

4 행을 "different"라는 텍스트로 바꾸고 싶다고 가정 해 봅시다. 다음과 같이 AWK를 사용할 수 있습니다.

awk '{ if (NR == 4) print "different"; else print $0}' input_file.txt > output_file.txt

AWK는 입력을 "필드"로 나눈 "레코드"로 간주합니다. 기본적으로 한 줄은 하나의 레코드입니다. NR본 레코드 수입니다. $0는 현재 완료 레코드를 나타냅니다 (레코드 $1의 첫 번째 필드 등). 기본적으로 필드는 줄의 단어입니다.

따라서 현재 행 번호가 4 인 경우 문자열 "different"를 인쇄하지만 변경되지 않은 행을 인쇄하십시오.

AWK에서, 포함 된 프로그램 코드 { }는 각 입력 레코드 에서 한 번 실행됩니다.

쉘이와 같은 것을 해석하지 못하게하려면 AWK 프로그램을 작은 따옴표로 인용해야합니다 $0.

편집 : 아래 의견에서 @chepner의 짧고 우아한 AWK 프로그램 :

awk 'NR==4 {$0="different"} { print }' input_file.txt

레코드 (예 : 행) 번호 4에 대해서만 전체 레코드를 "different"문자열로 바꾸십시오. 그런 다음 모든 입력 레코드에 대해 레코드를 인쇄하십시오.

분명히 내 AWK 기술은 녹슨 것입니다! 감사합니다, @chepner.

편집 : @Dennis Williamson의 더 짧은 버전도 참조하십시오.

awk 'NR==4 {$0="different"} 1' input_file.txt

이것이 작동하는 방식은 주석에 설명되어 있습니다. 1always는 true로 평가되므로 관련 코드 블록이 항상 실행됩니다. 그러나 관련 코드 블록이 없으므로 AWK가 전체 행을 인쇄하는 기본 작업을 수행합니다. AWK는 이와 같은 간결한 프로그램을 허용하도록 설계되었습니다.


3
조금 더 짧은 : awk 'NR==4 {$0="different"} { print }' input_file.txt.
chepner 2016 년

2
@chepner : 조금 더 짧습니다 :awk 'NR==4 {$0="different"}1' input_file.txt
추후 공지가있을 때까지 일시 중지되었습니다.

@DennisWilliamson, 나는 그것이 어떻게 작동하는지조차 모른다! 그 후행 1은 무엇을합니까? (참고 : 나는 그것을 테스트했고 그것은 실제로 작동한다! 나는 단지 어떻게 이해하지 못한다.)
steveha

1
나는 무조건적인 인쇄를 줄여 줄 방법이 있다고 생각했다! @stevaha : 1은 진정한 값이며 항상 일치하는 "패턴"을 의미합니다. 그리고 일치하는 기본 동작은 현재 줄을 인쇄하는 것입니다.
chepner 2016 년

19

이 테스트 파일 (test.txt)이 주어지면

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.

다음 명령은 첫 줄을 "줄 바꾸기 텍스트"로 바꿉니다.

$ sed '1 c\
> newline text' test.txt

결과:

newline text
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.

자세한 내용은 여기를 참조하십시오

http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/


2
이것이 정답이어야합니다. c 플래그는 필요한 것을 정확하게 수행합니다 (번호가 지정된 줄로 텍스트를 바꿉니다).
adelphus

stdout에서 파일을 에코하지 않는 sed를 사용한 대체 구문 : stackoverflow.com/a/13438118/4669135
Gabriel Devillers

정답이지만 왜 못생긴 줄 바꿈입니까? sed '1 cnewline text' test.txt그것도 할 것입니다.
dev-null

7

bash에서 N, M을 줄 번호로 바꾸고 xxx yyy를 원하는 것으로 바꿉니다.

i=1
while read line;do
  if((i==N));then
    echo 'xxx'
  elif((i==M));then
    echo 'yyy'
  else
    echo "$line"
  fi
  ((i++))
done  < orig-file > new-file

편집하다

실제로이 솔루션에는 문자 "\ 0" "\ t"및 "\"에 문제가 있습니다.

"\ t", 읽기 전에 IFS =를 넣어서 해결할 수 있습니다 : "\", -r

IFS= read -r line

그러나 "\ 0"의 경우 변수가 잘립니다. 순수한 bash에는 해결책이 없습니다. Bash의 변수에 널 문자 (\ 0)를 포함하는 문자열을 지정하십시오 . 그러나 일반 텍스트 파일에는 널 문자 \ 0 이 없습니다.

펄은 더 나은 선택이 될 것입니다

perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file

순수한 BASH 솔루션을 생각조차하지 못했습니다!
steveha 2016 년

4
# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
    local file="$1"
    local line_num="$2"
    local replacement="$3"

    # Escape backslash, forward slash and ampersand for use as a sed replacement.
    replacement_escaped=$( echo "$replacement" | sed -e 's/[\/&]/\\&/g' )

    sed -i "${line_num}s/.*/$replacement_escaped/" "$file"
}

3

Chepner의 훌륭한 답변. bash Shell에서 나를 위해 일하고 있습니다.

 # To update/replace the new line string value with the exiting line of the file
 MyFile=/tmp/ps_checkdb.flag

 `sed -i "${index}s/.*/${newLine}/" $MyFile`

here-
index줄 번호 없음
newLine-바꿀 새 줄 문자열입니다.


마찬가지로 아래 코드는 파일에서 특정 줄을 읽는 데 사용됩니다. 실제 파일에는 영향을 미치지 않습니다.

LineString=`sed "$index!d" $MyFile` 

here
!d-line no 이외의 행을 삭제 합니다. 따라서 파일에서 $index 출력을 no의 문자열로 가져옵니다 $index.


그러나 결과가 왜 표시되는지 내 배쉬 ${newline}입니까?
sikisis

1

Mac에서 사용한

sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name

-2

sed 명령에 매개 변수를 전달할 수도 있습니다.

test.sh

#!/bin/bash
echo "-> start"
for i in $(seq 5); do
  # passing parameters to sed
  j=$(($i+3))
  sed -i "${j}s/.*/replaced by '$i'!/" output.dat
done
echo "-> finished"
exit 

orignial output.dat :

a
b
c
d
e
f
g
h
i
j

./test.sh 를 실행 하면 새로운 output.dat가 제공됩니다.

a
b
c
replaced by '1'!
replaced by '2'!
replaced by '3'!
replaced by '4'!
replaced by '5'!
i
j

1
이 예제에 루프가 필요한 이유는 무엇입니까? line=5; sed -i "${line}s/.*/replaced by '$i'!/" output.dat
Rob

이것을 위해 루프가 필요하지 않습니다
chandu vutukuri
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.