sed를 사용하여 특정 줄을 문자열 변수로 바꾸는 방법은 무엇입니까?

sed를 사용하여 특정 줄을 문자열 변수로 바꾸는 방법은 무엇입니까?

file.txt예를 들어 다음과 같은 3줄의 콘텐츠가 있습니다 .

hello
hello
hello

이름이 지정된 변수 line=1와 string 변수 가 있습니다 substitute=hello1. line변수가 설명하는 줄의 문자열을 라는 새 문자열 변수로 바꾸고 싶습니다 substitute.

최종 변경 사항은 files.txt다음과 같습니다.

hello1
hello
hello

이 작업을 수행하려면 어떻게 해야 합니까 sed? 또는 awk? 그것이 당신이 원하는 것이라면 while 루프에서 변경될 수 있는 변수를 입력하겠습니다.

답변1

그리고 perl:

export line substitute
perl -pi -e '$_ = $ENV{substitute} . "\n" if $. == $ENV{line}' file.txt

GNU와 동일 awk:

export line substitute
gawk -i /usr/share/awk/inplace.awk '
  NR == ENVIRON["line"] {$0 = ENVIRON["substitute"]}
  {print}' file.txt

백슬래시, 명령 구분 기호 또는 개행 문자가 포함될 수 있는 경우 해당 값에 대해 일부 후처리를 수행해야 하기 때문에 sedPerl과 유사한 옵션을 지원하는 경우에도 여기서 사용하는 것은 이상적이지 않습니다. 바라보다-i$substitute&s"sed" 대체에 삽입된 문자열이 모든 메타 문자를 이스케이프하는지 확인하는 방법세부.

존재하다 gawk,사용하지 마세요-i inplace현재 작업 디렉터리(as or)에서 확장 기능을 먼저 gawk로드 하려고 하면 누군가가 해당 디렉터리에 악성 코드를 심었을 수 있습니다. 시스템과 함께 제공되는 확장 프로그램 의 경로 는 다를 수 있습니다. 출력을 참조하세요.inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

답변2

가정 line >0하고 항상정수, 다음과 같이 할 수 있습니다.

<infile head -n$(($line-1)); printf '%s\n' "$substitute"; tail -n +$(($line+1)) infile

line_number > file's_number_of_lines이면 $substitute파일 끝에 값이 추가 됩니다.$line

답변3

추가 정보가 없으면 다음 awk절차가 작동합니다.

awk -v where="$line" -v what="$substitute" 'FNR==where {print what; next} 1' file.txt
  • 쉘 변수 sum을 변수 sum 으로 $line가져 옵니다 .$substituteawkwherewhat
  • 1파일을 처리할 때 기본적으로 현재 줄( 규칙 블록 외부에서 벗어난 것으로 보이는 줄 ) 만 인쇄됩니다 { ... }.
  • 각 파일의 라인 카운터가 FNR에 저장된 라인 번호와 같을 때 where대체 문자열을 인쇄 what하고 실행을 위해 다음 입력 라인으로 점프합니다.

이는 awk파일을 내부에서 편집하지 않으므로 만족스러우면 출력을 리디렉션하고 결과 파일의 이름을 바꿔야 합니다. 또는 최신 버전의 GNU를 사용하면 이 옵션을 사용하여 파일을 수정할 awk수 있습니다 .-i inplace

노트(αГsнιι/Stéphane Chazelas/Ed Morton이 지적한 바와 같이) 문자열에 리터럴이 포함된 경우 이 방법이 이스케이프 시퀀스를 확장하기 때문에 substitute위 코드는 불규칙한 동작을 표시합니다 . \이 경우 awkStéphane Chazelas의 답변을 기반으로 한 대체 솔루션은 변수를 내보내고 참조하여 ENVIRON["substitute"]문제를 해결하는 것입니다(참조이 답변더 많은 정보를 알고 싶다면).

답변4

$   line=1 substitute=hello1
$ sed -nf - <<eof file 
  $line r $(t=$(mktemp);printf '%s\n' "$substitute" > "$t";echo "$t")
  $line!p
eof

sed 코드를 전달하기 위해 heredoc을 사용합니다. sed 코드는 -n원래 줄을 억제하는 옵션을 사용하여 파일을 읽고 jts 콘텐츠를 stdout에 배치합니다.

관련 정보