交換する前に、外部プログラムを介してsedキャプチャグループをパイプしますか?

交換する前に、外部プログラムを介してsedキャプチャグループをパイプしますか?

正規表現のRHSがそのプログラムの出力と等しくsedなるように、キャプチャグループを別のプログラムにパイプする方法はありますか?\1

たとえば、次のようにします。

sed 's/lorem ipsum \(foobar\)/\1/g' file.txt

「foobar」を別のプログラム(例えば)を介しtr 'o' 'a'て「faabar」にリンクして、「lorem ipsum foobar」を「lorem ipsum faabar」に置き換えますか?\1sed

これは単純な例です。 tr.

答え1

e(実行)修飾子を使用してGNU sedを使用できます。

eこの
コマンドを使用すると、シェルコマンドの入力をパターンスペースにパイプできます。置換が行われると、パターン空間内のコマンドが実行され、その出力がパターン空間を置き換えます。末尾の改行は抑制されます。実行するコマンドに NUL 文字が含まれている場合、結果は定義されません。これはGNU sed拡張です。

源泉)

しかし、指定されたキャプチャグループではなく、全パターン空間を実行して置換するため、ユーザビリティが制限される。だからあなたはかなり醜いバスケットボールを飛び越えなければなりません。

前任者。

$ echo 'lorem ipsum foobar' | sed '
    s/\(lorem ipsum \)\(foobar\)/printf "%s%s" "\1" "$(echo "\2" | tr o a)"/e
  '
lorem ipsum faabar

答え2

私が知っている限り:いいえ。

パターン空間は、以下を使用してファイルに書き込むことができます。

sed  '/example/w file'

しかし、キャプチャグループではありません。次のコマンドを使用して外部プログラムを実行できます。

sed 'e ls'

次のコマンドを使用してファイルを読み取ることができます

sed 'r file'

しかし、私はあなたが求めていることを達成するためのメンテナンス可能な方法を見ませんでした。正直なところ、あなたはここで役に立つかもしれない直前にいますsed

awkおそらくここではもう少し柔軟性がありますが、perl@ikkachuがすでに彼の意見で提案したように、これが最善の選択です。

簡単に考えると、それがどれほど些細なことなのかperl

while (<>){
    if (/(.*)(pattern)(.*)/){
        $pre=$1;
        $pat=$2;
        $post=$3;
        $repl=`filter_pgm $pat`;
        print $pre . $repl . $post;
    }
    else {
        print;
    }
}

(Perlにもっと精通した人のために:私はそれが醜く、おそらく本番で実行する前に多くのトリミングが必要になることを知っています)

関連情報