나는 이것을 알아 내려고 노력하고 있습니다 awk
. 예는 다음과 같습니다.
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
더 짧은 문자열을 선택하는 정규식을 작성할 수 있습니까?
@article{gjn,
이 긴 문자열 대신? :
@article{gjn, Author = {Grzegorz J. Nalepa},
나는 이 결과를 얻고 싶습니다:
Author = {Grzegorz J. Nalepa},
또 다른 예가 있습니다.
에코",기사 {gjn, 저자 = {Grzegorz J. Nalepa}, " | awk '{ sub(/,[^,]*,/,"");인쇄}' ↑ ^^^^^^
입력 문자열과 정규 표현식의 첫 번째 위치에 있는 문자를 @
쉼표( ) 문자로 변경했습니다. 더 짧은 문자열을 선택하는 정규식을 작성할 수 있습니까?,
.*
[^,]*
, Author = {Grzegorz J. Nalepa},
긴 문자열 대신? :
,article{gjn, Author = {Grzegorz J. Nalepa},
나는 이 결과를 얻고 싶습니다:
,article{gjn
답변1
이 이후의 @
첫 번째 항목을 선택하려면 ,
다음과 같이 지정해야 합니다.@[^,]*,
그 뒤에는 쉼표가 아닌 @
숫자 ( )가 오고 그 뒤에 쉼표( )가 옵니다.*
[^,]
,
이 방법은 동일하게 작동 하지만 뒤에 나오는 내용이 하나 이상의 문자이기 때문에 @.*?,
유사한 작업에는 작동하지 않습니다 . @.*?string
캐릭터를 부정하기는 쉽지만,정규식에서 문자열을 부정하는 것은 훨씬 더 어렵습니다..
또 다른 접근 방식은 입력을 전처리하여 string
입력에 나타나지 않는 문자로 바꾸거나 앞에 추가하는 것입니다.
gsub(/string/, "\1&") # pre-process
gsub(/@[^\1]*\1string/, "")
gsub(/\1/, "") # revert the pre-processing
입력에 대체 문자( \1
위)가 포함되어 있지 않다고 보장할 수 없는 경우 한 가지 접근 방식은 이스케이프 메커니즘을 사용하는 것입니다.
gsub(/\1/, "\1\3") # use \1 as the escape character and escape itself as \1\3
# in case it's present in the input
gsub(/\2/, "\1\4") # use \2 as our maker character and escape it
# as \1\4 in case it's present in the input
gsub(/string/, "\2&") # mark the "string" occurrences
gsub(/@[^\2]*\2string/, "")
# then roll back the marking and escaping
gsub(/\2/, "")
gsub(/\1\4/, "\2")
gsub(/\1\3/, "\1")
이는 고정 s에서는 작동 하지만 임의 의 string
정규식에서는 작동하지 않습니다.@.*?foo.bar
답변2
해결 방법을 제공하는 몇 가지 좋은 답변이 이미 있습니다. awk
탐욕스럽지 않은 일치를 수행할 수 없는 것에 대한 몇 가지 좋은 답변이 이미 있습니다.Perl 호환 정규식(PCRE). 대부분의 간단한 "일치 및 인쇄" 스크립트는 awk
쉽게 perl
사용할 수 -n
있으며 더 복잡한 스크립트는 다음을 사용하여 변환할 수 있습니다.a2pPerl 번역가에게는 어이가 없습니다.
진주Perl 스크립트와 PCRE를 사용하는 모든 것에서 사용할 수 있는 탐욕스럽지 않은 연산자가 있습니다. 예를 들어 GNU grep 옵션에서도 구현됩니다 -P
.
PCRE는동일하지 않음Perl의 정규식과 유사하지만 매우 유사합니다. 이는 속도가 매우 빠르고 Perl의 확장 정규식 향상 기능이 매우 유용하기 때문에 많은 프로그램의 정규식 라이브러리로 널리 선택됩니다.
~에서페레(1)매뉴얼 페이지:
By default, a quantified subpattern is "greedy", that is, it will match
as many times as possible (given a particular starting location) while
still allowing the rest of the pattern to match. If you want it to
match the minimum number of times possible, follow the quantifier with
a "?". Note that the meanings don't change, just the "greediness":
*? Match 0 or more times, not greedily
+? Match 1 or more times, not greedily
?? Match 0 or 1 time, not greedily
{n}? Match exactly n times, not greedily (redundant)
{n,}? Match at least n times, not greedily
{n,m}? Match at least n but not more than m times, not greedily
답변3
이것은 오래된 기사이지만 다음 정보는 다른 사람들에게 유용할 수 있습니다.
awk에서 탐욕스럽지 않은 RE 매칭을 수행하는 방법이 있습니다. 기본 아이디어는 match(string, RE) 함수를 사용하고 일치가 실패할 때까지 (테스트되지 않음) 다음과 같이 문자열 크기를 점차적으로 줄이는 것입니다.
if (match(string, RE)) {
rstart = RSTART
for (i=RLENGTH; i>=1; i--)
if (!(match(substr(string,1,rstart+i-1), RE))) break;
# At this point, the non-greedy match will start at rstart
# for a length of i+1
}
답변4
awk에서는 탐욕스럽지 않은 일치를 수행할 수 있는 방법이 없습니다. 그러나 원하는 결과를 얻을 수도 있습니다. sch의 제안이 해당 라인에 적용됩니다. 쉼표에 의존할 수 없지만 "작성자"가 항상 원하는 내용의 시작 부분인 경우 다음과 같이 할 수 있습니다.
awk '{ sub(/@.*Author/,"Author"); print }'
Author 앞의 문자 수가 항상 동일한 경우 다음을 수행할 수 있습니다.
awk '{ sub(/@.{21}/,""); print }'
전체 데이터 세트에서 데이터가 어떻게 보이는지 알아야 합니다.