GNU sedが "e"修飾子で実行されたコマンドに一致しない行の内容を追加するのはなぜですか?

GNU sedが

次のコマンドは、テキストのユーザー名とグループ名をUIDとGIDに正しく置き換えます。

echo "uidNumber=root" | sed -E 's/((u|g)idNumber=)([^,+]+)/echo -n \1; id -\2 \3/eg'
uidNumber=0

ただし、パターンに一致するテキストの前にテキストを追加すると、代替コマンドが実行される前に追加され、エラーが発生します。

echo "anotherAttr,uidNumber=root" | sed -E 's/((u|g)idNumber=)([^,+]+)/echo -n \1; id -\2 \3/eg'
h: line 1: anotherAttr,echo: command not found
0

パターンに一致するテキストの後にテキストを追加すると、同じことが起こるようです。この場合、テキストが追加されます。

echo "anotherAttr1,uidNumber=root,anotherAttr2" | sed -E 's/((u|g)idNumber=)([^,+]+)/echo -n \1; id -\2 \3/eg'
sh: line 1: anotherAttr1,echo: command not found
id: ‘root,anotherAttr2’: no such user

実行されたコマンドの前に一致しないテキストが追加されるのはなぜですか。これが起こらないようにするにはどうすればよいですか。

編集:他のユーザーは完全なラインマッチングを提案しましたが、これはg修飾子が正しく機能せず、許容される解決策ではありません。

ベストアンサー1

この問題は、修飾子の動作方法に関する根本的な誤解が原因で発生しますe

置換はs一度だけ適用することも、パターンバッファ全体(の場合g)に適用することもできます。eパターンバッファの内容は、交換後に実行されます。

修正はとても簡単です。ドルとスラッシュを避け、echo -n "パターンバッファに追加し、"パターンバッファに追加し、各代替コマンドをすべてサブシェル拡張に入れます。

p実行する内容を表示することでデバッグを支援するために追加されました。

echo "anotherAttr1,uidNumber=root,gidNumber=root,anotherAttr2" | sed -E 's/\\/\\\\/g;s/\$/\\$/g;s/^/echo "/;s/$/"/;s/((u|g)idNumber=)([^,+]+)/\1$(id -\2 \3)/peg'
echo "anotherAttr1,uidNumber=$(id -u root),gidNumber=$(id -g root),anotherAttr2"
anotherAttr1,uidNumber=0,gidNumber=0,anotherAttr2

おすすめ記事