Linux에서 stringy 검색 활용, 또는 lookahead 사용법

입질쾌감 물때표

stringy 검색 활용하는 방법

# sed에서 stringy 활용하는 방법 / super sed로 해야 처리가 가능하다.

$ cat sample.txt | ssed -n -R 's/(<a.*?>.*?<\/a>)/\1@/gp'

– R : 정규표현식을 펄형식으로 사용하기 위해서 정의해주는 것이다.
.*? : 최소 매칭으로 되지만, newline은 제외된다. 따라서 a태그 내용이 도중에 줄이 바뀌었을 경우에는 검색되지 않는다.

<a>태그의 시작과 끝을 나타내는 </a>의 태그를 <a.*>.*<\/a>라고 regex를 표현하게 되면 greedy 하게 검색하게 된다.
따라서 최소한 매칭이 되도록 설정하기 위해서는 “.*?”라고 정의해야 한다.

그러나 a태그가 두개 이상의 라인으로 묶여 있을 경우 위의 방법으로는 검색이 불가능해 진다.

A태그(블럭으로 구성되어있는)만 추출하는 방법

$ cat sample.txt | ssed -n -R '/<a.*/{/\/a>/!{:loopA;N;/\/a>/!bloopA;s/\n//g};s/(<a.*?>.*?<\/a>)/\1\n/gp}'
따라서 위의 방법으로 해결해야 한다.

$ cat sample.txt | sed -n -r '/<a.*/{/\/a>/!{:loopA;N;/\/a>/!bloopA;s/\n//g};p}' | grep -o -E '<a([^<]|<[^a])*<\/a>'
-o : 이 옵션은 매칭되는 텍스트만 출력해서 보여준다.
sed와 grep 옵션을 적절히 섞어서 아래 위의 처럼 만들어 줘야 한다.

 

lookahead 이해

Given the string foobarbarfoo:

bar(?=bar) finds the 1st bar (“bar” which has “bar” after it)
bar(?!bar) finds the 2nd bar (“bar” which does not have “bar” after it)
(?<=foo)bar finds the 1st bar (“bar” which has “foo” before it)
(?<!foo)bar finds the 2nd bar (“bar” which does not have “foo” before it)
You can also combine them:

(?<=foo)bar(?=bar) finds the 1st bar (“bar” with “foo” before it and “bar” after it)
Definitions

Look ahead positive (?=)

Find expression A where expression B follows:

A(?=B)
Look ahead negative (?!)

Find expression A where expression B does not follow:

A(?!B)
Look behind positive (?<=)

Find expression A where expression B precedes:

(?<=B)A
Look behind negative (?<!)

Find expression A where expression B does not precede:

(?<!B)A
Atomic groups (?>)

An atomic group is a non-capturing group that exits the group and throws away all alternatives after the first match of the pattern inside the group, so backtracking is disallowed.

A non-atomic group will allow backtracking, it will still find the first match, then if the matching ahead fails it will backtrack and find the next match, until a match for the entire expression is found or all possibilities are exhausted.

A non-atomic group in the expression (foo|foot)s applied to foots will:
match its 1st alternative foo, then fail as s does not immediately follow in foots, and backtrack to its 2nd alternative;
match its 2nd alternative foot, then succeed as s immediately follows in foots, and stop.
An atomic group in the expression (?>foo|foot)s applied to foots will match its 1st alternative foo, then fail as s does not immediately follow, and stop as backtracking is disallowed.
Lookahead 활용방법 (중간에 특정 단어가 포함 안된 문자열 찾기)

abcdefg12345
abcdpqw12345 내용일 경우, “중간에 efg가 포함된 텍스트는 빼고 abcd로 시작하고 12345로 끝나는 텍스트 패턴 찾기”

# Lookahead를 사용 ( grep 일경우 Perl Regex 사용 )
cat sample.txt | grep -P 'abcd(?!(.*efg)).*12345'

# Lookahead를 사용하지 않고 Lookahead를 만드는 방법 ( grep 일경우 -E extended regex 사용)
cat sample.txt | grep -E 'abcd(([^e]|e[^f]|ef[^g])*(ef?)?)12345'

 

# 설명
(1)abcd로 시작
(2)e로 시작안함, e+f로 시작안함, ef+g로 시작안함. 즉 (e),e(f),ef(g)를 제외한 모든 문자열을 말함 * -> 0개 또는 그 이상이 반복됨
; 하지만, e와 ef로 시작되는 문자열은 포함해야 함, 위의 (2)번에서 이런 문자열은 모두 제외했음
(3)(e 또는 ef)?의 문자가 있을수도 있고 없을수도 있음, 즉, (2)번의 경우중에서 e와 ef로 시작되는 문자는 있으면 포함됨

cat sample.txt | grep -E ‘(r(ef?))?’ <- r로 시작, re로 시작, ref로 시작하는 것, 그리고 다른 모든 포함
cat sample.txt | grep -E ‘r(ef?)?’ <- r로 시작, re로 시작, ref로 시작하는 라인만 출력
Capturing group

/((ca)+)\1/
\1 : 제일 먼저 나오는 괄호에 매칭이 된다. =((ca)+)
\2 : 다음에 나오는 괄호에 매칭이 된다. =(ca)+

/(ca|cb)\1/
\1 : ca 또는 cb에서 매칭되는 단어에 대해서 \1에 같은 텍스트가 저장된다.

$ echo “aaa aabbbbbaaaaaaaaaaabbbcccccddddeeee” | sed -n -r ‘s/^((a+b+)|(a+ a+b+))/\1@\2@\3/g;p’
aaa aabbbbb@@aaa aabbbbbaaaaaaaaaaabbbcccccddddeeee

\1 : ((a+b+)|(a+ a+b+)) : aaa aabbbbb
\2 : (a+b+) : 매칭 텍스트 없음
\3 : (a+ a+b+) : aaa aabbbbb

 

처음에 탭으로 시작하는 것을 모두 스페이스 패딩 * 4로 바꿔준다.

cat sample.txt | sed -n -r '/^\t/{:a;s/^(( {4})*)\t(.*)/\1\ \ \ \ \3/;ta;p}'

 

두개의 텍스트가 포함되어 있는 라인을 찾을때 사용하는 방법

grep 'A.*B\|B.*A'

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다