그래서 저는 sed에 있는 버퍼(모드 버퍼, 홀드 버퍼 등)의 존재를 이해하기 시작했고, sed 명령(예: 교체)의 결과를 다른 명령에 저장/저장하거나 재사용할 수 있는 쉬운 방법이 있는지 생각했습니다. /sed 전화?
파이프 출력을 대체한다고 가정해 보겠습니다.
somecommand | sed 's/somepattern/somethingelse/g'
위 교체의 출력을 어떻게든 재사용하고 싶습니다. 어떻게 해야 합니까? 다음을 사용할 수 있다는 것을 알고 있습니다.
- 임시 파일(예: 원시 mv + echo 등 사용)
- 또 다른 파이프 세트, sed 호출 및 xargs(예: sed ... | xargs -I{} sed ...)
하지만 위의 두 가지 모두 나를 막을 것입니다오직sed에 대한 단일 호출을 사용하십시오(여기서는 이것이 제가 원하는 것입니다).
그런 방법이 있다는 것을 알았다면 다음과 같이 했을 것입니다.
somecommand | sed -i 's/somepattern/somethingelse/g;s/[reusing result from last substitution]/someotherthings/g' file
[] 사이의 부분은 대체 결과를 패턴 등으로 재사용합니다.
가능한 해결책을 찾기 위해 sed 문서를 찾아보려 했지만 예제가 많지 않습니다.
모든 피드백/답변을 환영합니다.
추신: 위 예제의 출력은 실제로 요점은 아니지만 더 명확하게 하기 위해 다음 somecommand
으로 대체할 수 있습니다.
echo "hello"
문자 그대로.
제가 시도한 또 다른 방법은 이해하기 쉬운 예입니다.
#!/bin/sh
echo -e "hello\nworld" | sed -n '
l #enable debugging
'/hello/' { # match the string from the echo pipe/command output
s/hello/test/ #do a substitution
p #print
x # keep in
}'
x
전반부를 성공적으로 완료했습니다. 이제 다른 교체(또는 다른 sed 호출/작업/명령)와 함께 사용할 수 있도록 그 안에 있는 내용을 사용하는 방법을 알아야 합니다 .
제가 시도한 것은 다음과 같습니다(그러나 이번에는 실패했습니다).
#!/bin/sh
echo -e "hello\nworld" | sed -n '
l #enable debugging
'/hello/' { # match the string from the echo pipe/command output
s/hello/test/ #do a substitution
p #print
x # keep in
s/x/somethingelse/ # <---- what is failing
}'
이것은 작동하지 않습니다. 여기에 있는 것을 무엇 이든 얻을 수 있는 방법이 있을 것 같은데 x
, 모르겠어요.
답변1
내가 이해한 바에 따르면 과거 대체의 출력을 다른 대체의 패턴으로 사용하여 일종의 동적 검색 패턴이 필요합니다.
예제를 사용하는 것이 도움이 된다고 생각합니다. 이와 같은 파일이 주어지면
green2
gold1
blue3
gold2
red4
more gold2 to find
1
이제 각 행을 로 바꾸고 2
결과 행을 저장하여 해당 행이 다시 나타날 때 일부 작업을 수행할 수 있습니다. 이 예제 파일에서는 바꾸고 싶을 수도 있지만 gold2
다른 파일에서는 다를 수 있으므로 알 방법이 없습니다. 출력은 다음과 같아야합니다.
green2
gold2
blue3
replace
red4
more replace to replace
현실 세계에도 비슷한 작업이 있을 수 있으며 일반적으로 sed
다음과 같이 접근합니다.
sed -e 's/1/2/;tfound' -e 'G;s/\(..*\)\(.*\)\n\1$/replace\2/;P;d' -e ':found' -e h inputfile
개념은 결과 행을 보유 버퍼에 저장하고 역참조를 사용하여 각 행을 보유 버퍼와 일치시키는 것입니다. 상세히:
s/1/2/
분명한 부분은1
다음과 같습니다 .2
tfound
:found
대체할 때 분기 표시를 나타냅니다. 이 경우 해당 줄은 예약된 공간에 저장되고h
대체된 줄이 인쇄됩니다(d
인쇄하고 싶지 않으면 요소를 추가할 수 있습니다).- 이제 홀드 공간 패턴이 발생하는지 확인하는 라인 부분이 나옵니다.
G
홀드 공간은 현재 패턴 공간에 추가되므로 패턴 공간에는 다음이 포함됩니다. s/\(..*\)\(.*\)\n\1$/replace\2/
현재 줄에 두 그룹이 형성됩니다. 첫 번째 그룹은\1
개행 문자 다음에 반복되므로 이는 예약된 공간의 동적 패턴입니다(참고:..*
패턴은 최소한 하나의 문자여야 하므로 빈 예약어 사용을 피합니다). 일치하는 공백) 2는 줄의 나머지 부분이므로 삭제하면 안 되므로\2
교체처럼 재활용합니다.- 대체 항목이 있으면 해당 줄을 인쇄할 수 있지만 대체 항목이 없으면 추가된 내용을 제거해야 합니다. 로 이를 수행할 수 있지만 명령
s/\n.*//
을 사용하여P
첫 번째 행만 인쇄한 다음d
기본 출력을 피하기 위해 선택할 수도 있습니다.
이는 연속적으로 발생하는 동적 검색 패턴을 하나만 바꾸는 것으로 제한되지만 루프를 쉽게 추가하여 여러 교체에 대해 작동하도록 할 수 있습니다.
고쳐 쓰다: OP는 두 번째 단계가 원래 일치하는 행과 모든 후속 행(새 일치까지)에도 적용되어야 함을 명확히 했습니다.
hello
world
and test it
되어야 한다
세상을 바꾸고 바꿔라
이 경우 다른 글루 로직과 동일한 메커니즘을 사용합니다.
sed -ne '/hello/{s//test/;h;}' -e 'G;s/\(..*\)\(.*\)\n\1$/replace\2/;P'
옵션은 이제 모든 필수 출력이 명령을 통해 수행되므로 -n
모든 기본 출력을 억제합니다 . P
일치하는 문자열( hello
)에 대해 교체(빈 패턴은 마지막 패턴을 재사용한다는 의미)를 수행하고 이를 보유 버퍼에 넣은 후 다음 명령을 실행하면 다음 교체도 동일한 라인에서 수행됩니다.
업데이트 2:
연결된 예에서 hello
이러한 줄은 전혀 수정하면 안 됩니다. 몇 가지 수정을 통해 이를 수행할 수 있습니다.
sed -ne '/hello/{h;s//test/;x;}' -e 'G;s/\(..*\)\(.*\)\n\1$/replace\2/;P'