sed : 발견 된 경우 줄을 바꾸거나 찾을 수없는 경우 파일 끝에 추가하는 방법은 무엇입니까?


34

주석 만 포함 된 단일 입력 파일 (#로 시작)과 VARIABLE = value 행을 사용하면 발견 된 경우 단일 변수의 값을 바꾸고 그렇지 않은 경우 파일 끝에 해당 쌍을 추가 할 수 있습니까?

내 현재 방법은 첫 번째 패스에서 삭제 한 다음 두 번째 패스에서 파일 끝에 추가하여 작동하지만이 방법은 행 순서를 엉망으로 만듭니다 (또한 두 가지 다른 명령).

sed -r "/^FOOBAR=.*$/d"      -i samefile &&
sed -r "$ a\FOOBAR=newvalue" -i samefile

어쨌든 이것을 할 수 있습니까? 단일 sed 라인에서 라인 순서를 유지합니까? 다른 유틸리티 (awk, ...) 가이 작업을 수행하면 sed를 대신 사용합니다.

답변:


29

실제로 다음과 sed같이 매우 간단 합니다. 줄이 일치하면 h이전 공간에 복사 한 다음 s값 을 배제하십시오.
위선 $e에서 x홀드 스페이스와 패턴 스페이스를 변경 한 후 후자가 비어 있는지 확인하십시오. 비어 있지 않으면 대체가 이미 수행되지 않았 음을 의미합니다. 비어 있으면 일치하는 항목이 없으므로 패턴 공간을 원하는 variable = value 로 바꾸고 보류 버퍼의 현재 줄에 추가하십시오. 마지막으로 e가 x다시 변경됩니다.

sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile

위는 gnu sed구문입니다. 가지고 다닐 수 있는:

sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile

1
newvalue변수에 저장된 경우 어떻게 보 일까요?
user1810087

sed "/^${varName}=/{h;s/=.*/=${varValue}/};\${x;/^$/{s//${varName}=${varValue}/;H};x}" ${VARFILE}다음과 $같이 값이 저장되어있는 경우 에는 변수, 큰 따옴표를 사용하여 변수 대체를 허용 하고이 시점에서 대체가 아닌 a를 이스케이프합니다 $$varName.sed "/^${varName}=/{h;s/=.*/=${!varName}/};\${x;/^$/{s//${varName}=${!varName}/;H};x}" ${VARFILE}
DarkMukke

1
이 솔루션은 '간단한'롤이 아닙니다. 그러나 작동합니다. sed 매뉴얼 페이지는 가장 쉽게
알아볼 수있는 것이 아니며

18

아마 단축 될 수 있습니다. 단일 sed 명령이 아니며 grep도 사용하지만 기본적으로 원하는 것 같습니다. 한 줄이며 파일을 그 자리에서 편집합니다 (임시 파일 없음).

grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file || 
    sed "$ a\FOOBAR=newvalue" -i file

13

작업하기가 쉽지 sed않으므로 간단한 접근 방식 sed hold space이 있습니다. 에 익숙한 경우 hold spacedon_crissti 접근 방식을 사용하면 기존 줄의 내용을 보존 할 수있는 추가 기회가 제공되지만 일반적으로 매우 드 rare니다.

이 방법에서는 삭제하려는 줄을 제외한 모든 줄을 인쇄 한 다음 마지막에 교체를 추가하십시오.

sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile

1
기존이지만 오래된 값을 가질 수있는 파일을 업데이트하려는 경우이 버전이 매우 좋습니다.
길렘

3

다른 답변을 바탕으로 파일에 변수가 있으면 변수 값을 바꾸고 파일이 없으면 파일 끝에 추가하십시오 (게시 된 sed명령 이 아닌 ). 이것을 시도 할 수 있습니다 :

perl -ne '$c=1 if s/^FOOBAR=.*$/FOOBAR=newvalue/;  
             print; 
             END{print "FOBAR=newvalue" unless $c==1}' file > tmpfile && 
mv tmpfile file

1

"in place editing"이 자동적이지는 않지만 awk에서는 조금 더 쉽습니다.

awk -v varname="FOOBAR" -v newval="newvalue" '
    BEGIN {FS = OFS = "="}
    $1 == varname {$2 = newval; found = 1}
    {print}
    END {if (! found) {print varname, newval}}
' file > tempfile &&
mv tempfile file

1

간단하게 사용 grep하고 echo빈 레코드를 생성 :

grep -q '^FOOBAR=' somefile || echo 'FOOBAR=VALUE' >> somefile
sed -i 's/FOOBAR=.*$/FOOBAR=VALUE/' somefile 

각 줄은 오류 코드 0으로 이스케이프됩니다.


추가 명령을 추가하는 동안 라인 순서가 손실 grep되고echo
BlakBat

실제로 파일 끝에 새 항목을 삽입하지만 이전 값을 바꾸면 계속 주문하십시오.
MUY Belgium

0

실제로 다음과 함께 작동 sed -i '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile 합니다. 답변에서 -i가 누락되었습니다.


3
이것은 실제로 주석이며 원래 질문에 대한 답변이 아닙니다 . 작성자의 의견을 비판하거나 설명을 요청하려면 게시물 아래에 댓글을 남겨주세요. 언제든지 자신의 게시물 에 댓글 수 있으며 평판 이 충분 하면 게시물댓글 수 있습니다 . 댓글을 작성하려면 50 개의 평판이 필요한 이유를
DavidPostill

-1

펄을 사용 하여이 작업을 수행하고 그 자리에서 제대로 작동합니다.

grep ^FOOBAR= my.file && perl -i -ple "s/^FOOBAR=.+/FOOBAR=newvalue/g" my.file || echo FOOBAR=newvalue >> my.file

2
이 답변은 여러 가지면에서 나쁩니다 ! grepecho하고 perl대신에 모든 일을 perl? 또한 파일을 >> my.file읽을 때 파일 ( )에 쓰는가 ( grep my.file)?
vladr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.