sed: 다른 패턴 내에서 패턴 교체

sed: 다른 패턴 내에서 패턴 교체

$SOME_TEXT_HERE$이와 같은 값을 다음과 같은 값 으로 바꾸고 싶습니다 . @some.text.here@ 즉:

  1. 텍스트를 소문자로 변경
  2. $사용. . . 교체@
  3. 밑줄을 점으로 바꾸기

초기 문자열에는 관련 없는 텍스트가 얼마든지 있을 수 있습니다. 달러로 구분된 텍스트는 얼마든지 바꿀 수 있습니다. 달러로 구분된 텍스트는 밑줄로 구분된 하나 이상의 대문자로 구성될 수 있습니다.

1단계와 2단계를 수행하는 방법을 알고 있습니다. 3단계를 달러 기호 안에 있는 내용으로 제한하는 방법이 궁금합니다.

좋습니다. 예는 다음과 같습니다.

에서: Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$

도착하다: Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

나는 이것을 했다: echo 'Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$ ' |sed -e 's/\$\([A-Z]\+_\?\)\+\$/\L&/g' -e's/\$\(\([a-z]\+_\?\)\+\)\$/@\1@/g'

이것은 만든다: Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing_elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et_dolore_magna_aliqua@

@ 기호 내의 모든 단어를 얻기 위해 일치하는 그룹 결과를 반복하는 방법을 잘 모르겠습니다. 항상 마지막으로 일치하는 결과를 얻습니다.

답변1

펄 사용:

$ cat file
Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
$ perl -pe 's/\$([[:upper:]_]+)\$/"@" . lc $1 =~ tr[_][.]r . "@"/eg' file
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

여기에 사용된 Perl 표현식은 다음과 같습니다.

s/\$([[:upper:]_]+)\$/"@" . lc $1 =~ tr[_][.]r . "@"/eg

이는 첫 문자 $, 하나 이상의 대문자 또는 밑줄, 다른 문자로 $구성된 하위 문자열에 적용되는 대체 입니다.

$1대체 패턴은 연산자를 사용하여 패턴()의 대괄호 그룹과 일치하는 하위 문자열의 모든 밑줄을 점으로 변경한 tr다음 결과를 소문자로 변경 하는 Perl 표현식입니다 lc. 그런 다음 @결과 앞뒤에 문자를 추가합니다.

이는 Perl이 대체 텍스트를 단순한 텍스트가 아닌 Perl 표현식으로 처리하도록 하는 표현식 /e플래그 입니다. s///모든 일치 항목에 대해 교체를 반복하려면 이 플래그를 사용하십시오 /g.

답변2

$string입력이 쉘 의 변수 에 저장되면 다음을 zsh수행할 수 있습니다.

set -o extendedglob
string=${string//(#b)\$([A-Z]##(_[A-Z]##)#)\$/@${(L)match[1]//_/.}@}

perl같은

string=$(
  printf '%s\n' "$string" | perl -pe '
    s{\$[A-Z]+(_[A-Z]+)*\$}{lc$& =~ y/_$/.@/r}ge'
)

또는:

string=$(
  printf '%s\n' "$string" | perl -pe '
    s{\$[A-Z]+(_[A-Z]+)*\$}{$& =~ y/A-Z_$/a-z.@/r}ge'
)

차이점은 로케일에 따라 perl바이트 수준(ASCII 기반 시스템에서 ASCII 인코딩 필요)과 zsh문자 수준(문자로 디코딩할 수 없는 경우 바이트로 대체)에서 작동한다는 것입니다. 인코딩을 설정합니다. 개행 문자로 끝나는 경우에도 $string동작이 달라집니다 . 명령 대체를 통해 해당 문자가 제거되기 때문입니다.

답변3

GNU 사용 sed: (원하는 대로 sed)

$ sed -E 's/\$([A-Z]+([A-Z]*_)*[A-Z]+)\$/@\L\1@/g;s/@([a-z]+)_/@\1./g;s/_([a-z]+)@/\.\1@/g; :X s/(\.[a-z]+)_/\1\./g; tX'

산출:

$ echo 'Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$' | sed -E 's/\$([A-Z]+([A-Z]*_)*[A-Z]+)\$/@\L\1@/g;s/@([a-z]+)_/@\1./g;s/_([a-z]+)@/\.\1@/g; :X s/(\.[a-z]+)_/\1\./g; tX'
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

답변4

또 다른 약간 더 짧은 GNUsed

sed -E "s/\\\$([A-Z_]+)\\\$/@\L\1@/g; :X s/(@[a-z.]+)_/\1./; tX" file

이것이 @소스에서 자연스럽게 발생하지 않고 $처음에만 발생한다고 가정합니다.[A-Z_]

Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

이는 귀하의 예에서는 잘 작동하지만 대신 $BLAH_BLAH$blah_->를 사용하면 실패합니다.@blah.blah@blah.@blah.blah@blah_

편집하다Re @Quasimodo 댓글 +-> *두 번째sed

sed -E "s/\\\$([A-Z_]+)\\\$/@\L\1@/g; :X s/(@[a-z.]*)_/\1./; tX" file

Lorem $_IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
Lorem @.ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

관련 정보