를 \n
사용하여 대체 패턴을 추가 하면 패턴 sed
이 일치하지 않습니다. 예:
$ cat > alpha.txt
This is
a test
Please do not
be alarmed
$ sed -i'.original' 's/a test\nPlease do not/not a test\nBe/' alpha.txt
$ diff alpha.txt{,.original}
$ # No differences printed out
이 기능을 작동 시키려면 어떻게해야합니까?
답변
간단한 전화에서 나오지도 , 그것을 가지고 하나 개 , 즉 패턴 공간, 텍스트의 라인을. \n
입력에서 구분 된 한 줄의 텍스트 패턴 공간의 한 줄에는 없습니다 \n
… 그래서 정규 표현식이 아무것도 찾지 못하는 이유입니다.
패턴 공간으로 여러 줄을 읽고 놀랍게도 잘 처리 할 수 있지만 일반적인 노력보다 더 많은 노력이 필요합니다. Sed에는 이러한 유형의 작업을 허용하는 명령 세트가 있습니다. 여기 에 sed 의 명령 요약 링크가 있습니다. . 내가 찾은 최고의 것인데, 나는 굴러 갔다.
그러나 sed의 마이크로 명령을 사용하기 시작하면 “한 줄짜리”아이디어를 잊어 버리십시오. 느낌이들 때까지 구조화 된 프로그램처럼 배치하는 것이 유용합니다 … 놀랍도록 간단하고 똑같이 특이합니다. 텍스트 편집의 “어셈블러 언어”로 생각할 수 있습니다.
요약 : sed를 간단한 것, 그리고 조금 더 사용하기 위해 사용하십시오. 그러나 일반적으로 한 줄로 작업 할 수 없을 때 대부분의 사람들은 다른 것을 선호합니다. 다른
누군가가 다른 것을 제안하게 할 것입니다. 최선의 선택이 무엇인지 확실하지 않습니다 (sed를 사용하지만 펄을 충분히 알지 못하기 때문입니다.)
sed '/^a test$/{
$!{ N # append the next line when not on the last line
s/^a test\nPlease do not$/not a test\nBe/
# now test for a successful substitution, otherwise
#+ unpaired "a test" lines would be mis-handled
t sub-yes # branch_on_substitute (goto label :sub-yes)
:sub-not # a label (not essential; here to self document)
# if no substituion, print only the first line
P # pattern_first_line_print
D # pattern_ltrunc(line+nl)_top/cycle
:sub-yes # a label (the goto target of the 't' branch)
# fall through to final auto-pattern_print (2 lines)
}
}' alpha.txt
여기에는 동일한 스크립트가 있으며, 읽기 및 작업하기가 더 어려운 것으로 요약되어 있지만 일부는 확실하게 하나의 라이너를 호출 합니다.
sed '/^a test$/{$!{N;s/^a test\nPlease do not$/not a test\nBe/;ty;P;D;:y}}' alpha.txt
내 명령 “치트 시트”입니다
: # label
= # line_number
a # append_text_to_stdout_after_flush
b # branch_unconditional
c # range_change
d # pattern_delete_top/cycle
D # pattern_ltrunc(line+nl)_top/cycle
g # pattern=hold
G # pattern+=nl+hold
h # hold=pattern
H # hold+=nl+pattern
i # insert_text_to_stdout_now
l # pattern_list
n # pattern_flush=nextline_continue
N # pattern+=nl+nextline
p # pattern_print
P # pattern_first_line_print
q # flush_quit
r # append_file_to_stdout_after_flush
s # substitute
t # branch_on_substitute
w # append_pattern_to_file_now
x # swap_pattern_and_hold
y # transform_chars
답변
perl
대신에 사용하십시오 sed
:
$ perl -0777 -i.original -pe 's/a test\nPlease do not/not a test\nBe/igs' alpha.txt
$ diff alpha.txt{,.original}
2,3c2,3
< not a test
< Be
---
> a test
> Please do not
-pi -e
표준 “제자리에서 교체”명령 줄 순서이며 -0777은 perl이 파일 전체를 제거합니다. 자세한 정보는 perldoc perlrun 을 참조하십시오 .
답변
\n
기호를 다른 기호 로 바꾸고 평소대로 작동하는 것이 좋습니다 .
예 : 작동하지 않는 소스 코드 :
cat alpha.txt | sed -e 's/a test\nPlease do not/not a test\nBe/'
다음으로 변경할 수 있습니다.
cat alpha.txt | tr '\n' '\r' | sed -e 's/a test\rPlease do not/not a test\rBe/' | tr '\r' '\n'
아무도 모른다면 \n
유닉스 라인 엔딩, \r\n
윈도우, \r
클래식 맥 OS입니다. 일반적인 UNIX 텍스트는 \r
기호를 사용하지 않으므로이 경우에 사용하는 것이 안전합니다.
이국적인 기호를 사용하여 \ n을 임시로 바꿀 수도 있습니다. 예를 들어-\ f (양식 피드 기호). 여기에서 더 많은 기호를 찾을 수 있습니다 .
cat alpha.txt | tr '\n' '\f' | sed -e 's/a test\fPlease do not/not a test\fBe/' | tr '\f' '\n'
답변
모든 것을 고려하여, 전체 파일을 삼키고는 갈 수있는 가장 빠른 방법이 될 수 있습니다.
기본 구문은 다음과 같습니다.
sed -e '1h;2,$H;$!d;g' -e 's/__YOUR_REGEX_GOES_HERE__...'
파일이 엄청 나면 전체 파일을 고 블링하는 것이 옵션이 아닐 수 있습니다. 그러한 경우, 여기에 제공된 다른 답변은 작은 메모리 공간에서 작동하도록 보장되는 맞춤형 솔루션을 제공합니다.
다른 모든 핵 및 슬래시 상황의 경우, -e '1h;2,$H;$!d;g'
원래 sed
정규 표현식 인수 앞에 붙는 것만으로도 작업이 완료됩니다.
예 :
$ echo -e "Dog\nFox\nCat\nSnake\n" | sed -e '1h;2,$H;$!d;g' -re 's/([^\n]*)\n([^\n]*)\n/Quick \2\nLazy \1\n/g'
Quick Fox
Lazy Dog
Quick Snake
Lazy Cat
무엇을 -e '1h;2,$H;$!d;g'
합니까?
1
, 2,$
, $!
부품 라인이 직접 다음 명령이 실행 라인이 한도를 지정자입니다.
1
: 첫 줄만2,$
: 두 번째부터 시작하는 모든 줄$!
: 마지막 이외의 모든 줄
확장되어 N 라인 입력의 각 라인에서 발생합니다.
1: h, d
2: H, d
3: H, d
.
.
N-2: H, d
N-1: H, d
N: H, g
g
명령 라인에서 지정된 것이 아니라, 위의 d
명령은 특별한 조항이있다 ” 시작 다음주기를. “이것은 방지 g
마지막을 제외한 모든 라인에서 실행.
각 명령의 의미는 다음과 같습니다.
- 제
h
다음H
각 광고 카피들로의 입력 라인을 상기sed
집의 보류 공간 . (임의의 텍스트 버퍼를 생각하십시오.) - 그런
d
다음 각 행을 버려서 해당 행이 출력에 기록되지 않도록합니다. 그러나 홀드 공간 은 유지됩니다. - 마지막으로, 맨 마지막 줄에
g
로부터 모든 라인의 축적 복원 보류 공간을 그 때문에sed
(오히려 라인 한번에 한 방식에 비해) 전체 입력에서의 정규 표현식을 실행할 수 있으며, 따라서 할 수있다 에 일치합니다\n
.
답변
sed
: 세 가지 명령 멀티 라인 작업을 관리 할 수있다 N
, D
그리고 P
(에 비교 정상 n
, d
과 p
).
이 경우 패턴의 첫 번째 행을 일치시키고 N
두 번째 행을 패턴 공간 에 추가 한 다음 s
대체를 수행 하는 데 사용할 수 있습니다.
다음과 같은 것 :
/a test$/{
N
s/a test\nPlease do not/not a test\nBe/
}
답변
당신은 할 수 있지만 어렵습니다 . 다른 도구로 전환하는 것이 좋습니다. 바꾸려는 텍스트의 어떤 부분과도 일치하지 않는 정규식이 있다면 GNU awk에서 awk 레코드 구분 기호로 사용할 수 있습니다.
awk -v RS='a' '{gsub(/hello/, "world"); print}'
검색 문자열에 연속 된 줄 바꿈이 두 개 이상없는 경우 awk의 “단락 모드”(하나 이상의 빈 줄이 별도의 레코드)를 사용할 수 있습니다.
awk -v RS='' '{gsub(/hello/, "world"); print}'
쉬운 해결책은 Perl을 사용하고 파일을 메모리에 완전히로드하는 것입니다.
perl -0777 -pe 's/hello/world/g'
답변
나는 이것이 2 줄 일치에 대한 sed 솔루션이라고 생각합니다.
sed -n '$!N;s@a test\nPlease do not@not a test\nBe@;P;D' alpha.txt
3 줄 일치를 원하면 …
sed -n '1{$!N};$!N;s@aaa\nbbb\nccc@xxx\nyyy\nzzz@;P;D'
4 줄 일치를 원한다면 …
sed -n '1{$!N;$!N};$!N;s@ ... @ ... @;P;D'
“s”명령의 교체 부품이 줄을 줄이면 이와 같이 조금 더 복잡해집니다
# aaa\nbbb\nccc shrink to one line "xxx"
sed -n '1{$!N};$!N;/aaa\nbbb\nccc/{s@@xxx@;$!N;$!N};P;D'
repacement 부분이 선을 키우면 다음과 같이 조금 더 복잡해집니다
# aaa\nbbb\nccc grow to five lines vvv\nwww\nxxx\nyyy\nzzz
sed -n '1{$!N};$!N;/aaa\nbbb\nccc/{s@@vvv\nwww\nxxx\nyyy\nzzz@;P;s/.*\n//M;P;s/.*\n//M};P;D'