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

関連情報