텍스트 파일에서 큰따옴표나 작은따옴표 안의 문자열을 찾고 싶습니다(텍스트 파일은 여러 줄입니다).
예를 들어:
I have a
test "foo bar1" test2 "foo\"bar2",
"foo 'bar3",
'foo bar4', 'foo \'bar5', 'foo "bar6',
출력됩니다
foo bar1
foo\"bar2
foo 'bar3
foo bar4
foo \'bar5
foo "bar6
난이도는 다음과 같습니다.
- 텍스트 파일은 여러 줄입니다.
- 큰따옴표나 작은따옴표를 따옴표 안에 이스케이프 처리했을 수 있습니다.
- 큰따옴표 안에 작은따옴표를 넣을 수 있습니다.
- 작은따옴표 안에 큰따옴표가 있을 수 있습니다.
- 따옴표는 쌍으로 일치해야 합니다.
답변1
Perl의 일치 시간 코드 보간 기능을 사용하여 (??{ match time regex })
이 문제를 해결할 수 있습니다. 기본적으로 이것이 수행하는 작업은 일치하는 참조를 기반으로 정규식 엔진이 해당 참조 쌍을 캡처할 수 있도록 해당 참조에 해당하는 유효한 정규식을 배치하는 것입니다.
$ perl -lne '
print substr($&, 1, -2+length($&))
while
/(?:(["'\''])(??{q<(?:[^\\\\>.$1.q<]|\\\\.)*>.$1}))/gx;
' file
결과:
foo bar1
foo\"bar2
foo 'bar3
foo bar4
foo \'bar5
foo "bar6
위의 내용을 보다 원활하게 다시 작성하면 다음과 같습니다.
$ perl -lne '
BEGIN {
$genRE = sub {
my $openingQ = shift;
# look in the Notes below for why
qq<(?:[^\\\\${openingQ}]|\\\\.)*>
};
}
print $2
while
/
(["'\'']) (?#: opening quote)
((??{ $genRE->($1) })) (?#: run of in between quote pair stuff)
\1 (?#: corresponding closing quote)
/gx;
' file
노트::
"........"
성냥/"[^"]*"/
"...... \"......"
성냥/"(?:[^\\"]|\\.)*"/
- 작은따옴표도 비슷합니다.
답변2
또 다른 perl
방법:
perl -lne 'print $2 while m{(["'\''])((?:\\.|(?!\1).)*+)\1}g'
부정 예측 연산자는 여기서 (?!\1).
첫 번째 캡처링 그룹과 일치하는 문자 이외의 문자를 일치시키는 데 사용됩니다. 간단히 재정의 '...'
하고 대소문자를 구분할 수도 있습니다 "..."
.
perl -lne 'print $1 while m{(?|"((?:\\.|[^"])*+)"|'"'((?:\\\.|[^'])*+)')}g"
답변3
이건 어려워. 나는 해결책이 없습니다. 이 작업에 가장 적합한 도구가 무엇인지조차 모르겠습니다.
나는 가깝다:
$ grep -oP '((?<!\\)"\K.*?(?=(?<!\\)"))|'"((?<!\\\\)'\K.*?(?=(?<!\\\\)'))" input
foo bar1
foo\"bar2
foo 'bar3
foo bar4
,
foo \'bar5
,
foo "bar6
한 줄에 여러 개의 일치 항목이 있는 경우 앞 문자열의 닫는 따옴표가 중간 텍스트의 시작 따옴표와 일치한다는 문제가 있습니다. 뒤돌아보기는 고정된 길이여야 하기 때문에 짝수 개의 따옴표를 사용하여 긍정적인 뒤돌아보기를 중지할 수 없습니다. 적어도 grep
.
'
게다가, 그 안에 있는 몇몇 경기(또는 그 반대)도 "
아무리 말해도 흥미롭습니다.
어쩌면 awk
더 나은 도구일 수도 있습니다. 이를 통해 어떤 참조 유형이 먼저 나오는지 확인하고 다음 참조 유형으로 건너뛰어 앞에 백슬래시가 있는지 확인할 수 있습니다.