これは私のコードです。
printf '%s' '{$aaa} \\{$bbb} \{$ccc} {$ddd' | sed -r -e 's/(^|[^\\])\{\$/\1\$\{/g' -e 's/\\\\\{\$/\\\\\$\{/g'
結果:
${aaa} \\${bbb} \{$ccc} ${ddd
{$ddd
閉じ括弧で終わらないため、置き換えるべきでない最後のパターンを除いて、結果は正常です}
。
sedを使用してこれを行うにはどうすればよいですか?
また、2つの実際の表現を組み合わせる方法を知っていれば大歓迎です(私にとってはそれほど重要ではありません)。
編集:括弧も($foo)
次のことを行います。$(foo)
答え1
最初の作業から始めて閉じるまでのみ変更を行います{}
。
printf '%s' '{$aaa} \\{$bbb} \{$ccc} {$ddd' | sed 's/{$\([^}]*\)}/${\1}/g'
つまり、{$
終わりから終わりまでのすべての内容}
が に配置されるので、\(\)
代替文字列でこれを逆参照できます\1
。出力:
${aaa} \\${bbb} \${ccc} {$ddd
ここでバックスラッシュエスケープについて説明します。あなたのソリューションは\{$aaa}
(触れないでください)と\\{$aaa}
(交換)には効果的ですが、何ですか\\\{$aaa}
?望ましくない変更が行われます。
したがって、最初にすべての二重バックスラッシュを削除することをお勧めします。たとえば、文字列の一部になることができない文字の組み合わせに置き換えて、#1
最終的に再変更します。これにより、単一のバックスラッシュにのみ集中できます。
printf '%s' '{$aaa} \\{$bbb} \{$ccc} \\\{$eee} {$ddd' | sed 's/\\\\/#1/g;s/{$\([^}]*\)}/${\1}/g;s/#1/\\\\/g'
最後に、これを削除するには、最後に次のように\{
変更して再交換することができます。#2
printf '%s' '{$aaa} \\{$bbb} \{$ccc} \\\{$eee} {$ddd' | sed 's/\\\\/#1/g;s/\\{/#2/g;s/{$\([^}]*\)}/${\1}/g;s/#2/\\{/g;s/#1/\\\\/g'
結果:${aaa} \\${bbb} \{$ccc} \\\{$eee} {$ddd
これはバックスラッシュの数に関係なく機能します。
しかし、#
あなたと同じキャラクターを勝手に使えないとしたらどうでしょうか?改行文字は行の一部にできないため、改行文字を使用できます。あなたはGNUを使っているようですので、これを行うことがsed
できます。
printf '%s' '{$aaa} \\{$bbb} \{$ccc} \\\{$eee} {$ddd' | sed 's/\\\\/\n1/g;s/\\{/\n2/g;s/{$\([^}]*\)}/${\1}/g;s/\n2/\\{/g;s/\n1/\\\\/g'
POSIXで実行するには、sed
次のものが必要です。解決策
答え2
POSIXを使用すると、sed
次のことができます。
sed -e '
# case for {$var}
s/ \(\(\\\\\)\{0,\}\){\$\([^ }]*\)}/ \1${\3}/g
s/^\(\(\\\\\)\{0,\}\){\$\([^ }]*\)}/\1${\3}/
# case for ($var)
s/ \(\(\\\\\)\{0,\}\)(\$\([^ )]*\))/ \1$(\3)/g
s/^\(\(\\\\\)\{0,\}\)(\$\([^ )]*\))/\1$(\3)/
' input_file
スペースがファイルの唯一のスペースであると仮定します。もちろん、TABを使用して問題を解決し、OPの練習として残すこともできます。利用可能な拡張機能を使用すると、上記の内容をさらに簡素化できますが、より大きな適用性を提供するソリューションを提供したいとGNU sed
思います。POSIX