마무리할 일이 있어요. & 내부 또는 사이의 모든 항목을 #으로 바꿔야 합니다 <ex>
</ex>
. 실제적인 예는 다음과 같습니다:
a & b & c <ex> a & b & c </ex> a & b & c
<ex>
다시 말하지만, & 내부 와 이전 의 모든 항목을 바꿔야 합니다.</ex>
예상 출력:
a & b & c <ex> a # b # c </ex> a & b & c
이 작업을 수행하는 방법에 대한 설명을 게시하십시오.
편집 #1
sed
AS400 시스템에서 실행할 예정이므로 Perl이나 기타 인터프리터를 설치할 수 없으므로 솔루션을 제공해주세요 .
답변1
<ex>...</ex>
각 줄이 한 번만 나타나는 경우:
sed -e :1 -e 's@\(<ex>.*\)&\(.*</ex>\)@\1#\2@;t1'
여러 항목이 있을 수 있고 중첩되지 않은 경우(또는 중첩되어 &
가장 깊은 항목만 바꾸려는 경우):
sed '
s|_|_u|g # replace all underscores with "_u"
s|(|_o|g # replace all open parentheses with "_o"
s|)|_c|g # replace all close parentheses with "_c"
s|<ex>|(|g # replace all open ex tags with "("
s|</ex>|)|g # replace all close ex tags with ")"
:1 # a label
s/\(([^()]*\)&\([^()]*)\)/\1#\2/g
# find:
# an open parentheses,
# some non-parentheses chars (captured),
# an ampersand,
# some non-parentheses chars (captured) and
# a close parentheses,
# replace with
# the first captured text,
# an octothorpe
# the second captured text,
# globally in the current record.
t1 # if there was a successful replacement, goto label "1",
# else carry on
s|(|<ex>|g # restore open tags
s|)|</ex>|g # restore close tags
s|_o|(|g # restore open parentheses
s|_c|)|g # restore close parentheses
s|_u|_|g # restore underscores
'
중첩될 수 있고 이를 둘러싸는 것으로 바꾸려는 경우:
sed '
s|_|_u|g;s|(|_o|g;s|)|_c|g
s|<ex>|(|g;s|</ex>|)|g;:1
s/\(([^()]*\)(\([^()]*\))\([^()]*)\)/\1_O\2_C\3/g;t1
:2
s/\(([^()]*\)&\([^()]*)\)/\1#\2/g;t2
s|(|<ex>|g;s|)|</ex>|g
s|_O|<ex>|g;s|_C|</ex>|g
s|_o|(|g;s|_c|)|g;s|_u|_|g'
답변2
Perl(버전 5.14 필요)을 사용하여 다음을 수행하세요.
perl -pe 's%(<ex>.*?</ex>)% $1 =~ s/&/#/gr %eg'
이전 버전에서는 더 장황해야 했습니다.
perl -pe 's%(<ex>.*?</ex>)% ($_x = $1) =~ s/&/#/g; $_x %eg'
지침: <ex>
태그 사이의 모든 내용을 에 넣고 $1
& $1
를 #으로 바꾸십시오.
답변3
또 다른 펄 명령,
$ perl -pe 's/&(?=(?:(?!<ex>|<\/ex>).)*<\/ex>)/#/g' file
a & b & c <ex> a # b # c </ex> a & b & c
위의 명령을 설명하기 전에, Negative Lookahead와 Positive Lookahead가 실제로 무엇을 하는지 설명하겠습니다.
정규식에서는 (?=...)
긍정적인 예측을 의미합니다. 둘러보기(예: 긍정적 및 부정적 미리보기, 긍정적 및 부정적 미리보기)는 너비가 0인 일치 항목을 만듭니다. 즉, 어떤 문자와도 일치하지 않습니다. 일반적으로 긍정적 및 부정적 예측은 상태 확인 목적으로 사용됩니다. (?:...)
비캡처 그룹 이라고도 합니다. 즉, 비캡처 그룹 내의 패턴만 일치됩니다. 어떤 문자도 캡처하지 않습니다.
(?!<ex>|<\/ex>)
문자열<ex>
또는 .와 일치할 수 없습니다</ex>
.(?:(?!<ex>|<\/ex>).)
실제로 의미하는 바는 먼저 다음 3~4개의 문자를 찾고 다음 3~4개의 문자가<ex>
또는 이 될 수 없는지 확인한다는 것입니다</ex>
..
이 조건이 충족되면 다음 문자만 일치됩니다.(?:(?!<ex>|<\/ex>).)*
문자열<ex>
또는 가 감지될 때까지 위의 단계를 0번 이상 수행합니다.</ex>
이 두 문자열 중 하나를 찾으면 갑자기 다음 문자 일치가 중단됩니다.(?:(?!<ex>|<\/ex>).)*<\/ex>
다음</ex>
문자열과도 일치합니다. 이것은 모두 예측에 반영됩니다.&(?=(?:(?!<ex>|<\/ex>).)*<\/ex>)
&
마지막으로 위 조건을 만족하는 문자가 뒤에 오는 경우에만 문자와 일치합니다. 즉,&
다음에는 속하지 않는 문자가 와야 하거나 닫는 표시가 0번 이상 와야<ex>
합니다 .</ex>
</ex>
답변4
중첩되지 않고 줄에서 두 번 이상 발생하면 도움이 될 수 있습니다.
#cat plop
>a & b & c <ex> a & b & c </ex> a & b & c <ex> a & b & c </ex> a & b & c
#cat plop |sed -e :1 -e 's@\(<ex>[^(</ex>)]*\)&\(.*</ex>\)@\1+\2@;t1'
>a & b & c <ex> a + b + c </ex> a & b & c <ex> a + b + c </ex> a & b & c