sed 단어 경계: 명령 매크로를 명령으로 대체

sed 단어 경계: 명령 매크로를 명령으로 대체

실행할 기본 명령 대신 "명령 매크로"가 사용되는 코드 조각을 상속받았습니다 . $TR예를 들어 명령 매크로를 참조하는 셸 명령으로 다시 변환하는 tr데 사용하고 싶습니다 . sed문제는 단어 경계에 있습니다.

$ echo '$TR $TRUE $TRUNCATE "$TR ($TR' | sed s/\$TR/tr/g
tr trUE trUNCATE "tr (tr

분명히 잘못된 것입니다. 그러나 다음을 \b사용하여 번역된 단어 경계를 설정하려고 하면 작동하지 않습니다.

$ echo '$TR $TRUE $TRUNCATE "$TR ($TR' | sed s/\$TR\b/tr/g
$TR $TRUE $TRUNCATE "$TR ($TR

매크로 길이를 역순으로 검색하는 것(즉 $TRUNCATE, 먼저 교체 $TRUE, 다음 교체)은 독립적인 콘텐츠만 으로 변환되는 $TR경우도 있으므로 완전한 솔루션은 아닙니다 .$TS $TS_FORMAT$TSts

\b여기서 단어 경계 태그가 작동하지 않는 이유가 있나요? 이 문제를 해결하려면 어떻게 해야 합니까?

$ sed --version
sed (GNU sed) 4.7
Packaged by Debian
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
Paolo Bonzini, Jim Meyering, and Assaf Gordon.
GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.
E-mail bug reports to: <[email protected]>.

편집하다

명령 매크로를 정의하는 파일에는 FQFN이 부적절하더라도(예: while return $TRUE으로 정의됨 ) 대체된 모든 명령의 정규화된 파일 이름이 포함됩니다. 이로 인해 참조 시 디스크의 파일이 실행되므로 명령 매크로(이 경우)를 사용하면 성능에 상당한 영향을 미칠 수 있습니다./usr/bin/truetype truetrue is a shell builtin$TRUE

목표는 명령 매크로가 source정의된 d 파일에서 사라지고 제거될 수 있도록 코드 베이스의 파일을 업데이트하여 향후 코드 독자와 유지관리자가 명령 매크로를 전혀 다룰 필요가 없도록 하는 것입니다.

답변1

sed 표현식은 인용되지 않았으므로 쉘은 이를 \b일반으로 변환할 수 있습니다 b. 예를 들어 Bash에서는 다음과 같습니다.

set -x

$ echo '$TR $TRUE $TRUNCATE "$TR ($TR' | sed s/\$TR\b/tr/g
+ sed 's/$TRb/tr/g'
+ echo '$TR $TRUE $TRUNCATE "$TR ($TR'
$TR $TRUE $TRUNCATE "$TR ($TR

하지만

$ echo '$TR $TRUE $TRUNCATE "$TR ($TR' | sed 's/\$TR\b/tr/g'
+ sed 's/\$TR\b/tr/g'
+ echo '$TR $TRUE $TRUNCATE "$TR ($TR'
tr $TRUE $TRUNCATE "tr (tr

그러나 sed가 작업에 적합한지 의문이 듭니다. 아마도 envsubstex와 같은 것을 고려해 볼 수도 있습니다.

$ echo '$TR $TRUE $TRUNCATE "$TR ($TR' | env TR=tr TRUE=true TRUNCATE=truncate envsubst
tr true truncate "tr (tr

답변2

휴대용 솔루션의 경우 다음을 사용할 수 있습니다 perl(GNU가 sed복사된 위치 \b).

perl -pe 's/\$(?|(TR|TRUE|TRUNCATE|TS)\b|\{((?1))\})/\L$1/g'

대체 후의 소문자 내용은 실제로 / \L에서 나옵니다 . GNU 구현에서도 사용할 수 있지만 다른 구현에서는 표준이 아니거나 이식 가능하지 않습니다.exvisedsed

  • (?1)(TR|TRUE|TRUNCATE|TS)첫 번째 대괄호 쌍에 포함된 정규식을 호출하고 여기서 사용하면 변형과 일치하기 위해 교대로 반복할 필요가 없습니다 ${VAR}.
  • (?|...)~이다분기 재설정. (?:...)​주요 차이점은 (a(x)|b(y))end up, by in 및 in과 일치하는 내용이 ->, ->,x$2y$3(...)$1(?:a(x)|b(y))x$1y$2(?:...)그룹하지만포착, 및 에서는 (?|a(x)|b(y))와 일치하거나 로 끝나는 콘텐츠입니다.xy$1

GNU를 사용하면 sed다음을 수행할 수 있습니다.

vars='(TR|TRUE|TRUNCATE|TS)'
sed -E "s/\\\$($vars\>|\{$vars\})/\L\2\3/g"

\>(또한 ex/ )는 다른 사전주의와 일관성을 유지하기 위해 여기에서 viPerl 스타일 대신 사용되었지만 여기서의 작동 원리는 동일합니다.\b\L\b

관련 정보