\n
using 을 대체하기 위해 패턴을 추가하면 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
어떻게 작동하게 할 수 있나요?
답변1
가장 간단한 호출에서sed,그것은하나패턴 공간의 텍스트 라인. \n
입력에서 구분된 텍스트 1줄입니다. 패턴 공간에는 한 줄도 없습니다 \n
. 그래서 정규 표현식이 아무것도 찾지 못하는 것입니다.
여러 줄을 패턴 공간으로 읽어 들여 놀랍도록 잘 조작할 수 있지만 평소보다 훨씬 더 많은 노력이 필요합니다. Sed에는 이러한 유형의 작업을 허용하는 명령 세트가 있습니다...여기 링크가 있습니다sed 명령 요약. 이것은 내가 찾은 것 중 최고이며 나를 흥분시킵니다.
그러나 일단 sed의 마이크로 명령을 사용하기 시작하면 "한 줄" 개념은 잊어버리십시오. 느낌을 얻을 때까지 구조화된 프로그램처럼 배치하는 것이 유용합니다. 매우 간단하면서도 독특합니다. 텍스트 편집의 "어셈블리 언어"라고 생각하면 됩니다.
요약: 간단한 작업에는 sed를 사용하세요. 어쩌면 그 이상일 수도 있지만 일반적으로 한 줄을 사용하는 것 이상일 때 대부분의 사람들은 다른 것을 선호합니다...
다른 사람들이 다른 것을 제안하도록 하겠습니다. 옵션은 (저는 sed를 사용하겠지만 그건 제가 Perl을 잘 모르기 때문입니다.)
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
답변2
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이 전체 파일을 읽도록 합니다. 바라보다퍼독 페렌이에 대해 자세히 알아보세요.
답변3
\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
UNIX 줄 끝은 \r\n
- windows, \r
- classic Mac 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'
답변4
모든 상황을 고려했고,전체 파일을 삼켜 버리세요아마도 가장 빠른 방법 일 것입니다.
기본 구문은 다음과 같습니다.
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
s 가 뒤따르는 각 줄의 첫 번째 줄은H
해당 입력 줄을sed
s 에 복사합니다.예비 공간. (임의의 텍스트 버퍼를 생각해 보세요.)- 그런 다음
d
해당 라인이 출력에 기록되지 않도록 각 라인을 삭제합니다. 이것예비 공간하지만 여전히 유지됩니다. - 마지막으로 마지막 줄에서
g
다음에서 복원합니다.예비 공간이를sed
통해 (한 번에 한 줄이 아닌) 전체 입력에 대해 정규식을 실행할 수 있으므로\n
s와 일치할 수 있습니다.