以下の food.txt ファイルがあります。
mangoes|foo|faa
oranges|foo|faa
chocolates|foo|baz
交換しようとしています。金持ちそしてバー条件が満たされたらbaz。 (ここではregex b * zを使うつもりです)
現在、以下のsedコマンドを使用していますが、既存のファイルを直接変更するわけではありません。また、正規表現(b*z)も使用できません。
sed '/baz/s/foo/bar/g' food.txt
既存のファイルを直接変更するには、「sed」以外に他の方法を提案してください。
PS:試してみましたが、sed -i
sed以外のコマンドを使用したいと思います。
mobaxterm(OS - Windows)を使用しています。
ベストアンサー1
sed
この状況で使用するのに問題はないと思います。これは仕事に適したツールです。
あなたのコマンドは(与えられたデータに対して)うまく機能します。
$ sed '/baz/s/foo/bar/g' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
正規表現を使用して、|b
行の終わり(行のどこにもない)で始まり、終わるすべての文字列を一致させます。z
baz
$ sed '/|b.*z$/s/foo/bar/g' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
ファイルを変更するには(GNUを使用sed
):
$ sed -i '/|b.*z$/s/foo/bar/g' food.txt
または(すべてのsed
実装):
$ sed '/|b.*z$/s/foo/bar/g' food.txt >tmpfile && mv tmpfile food.txt
以下も使用できますawk
。
$ awk 'BEGIN { OFS=FS="|" } $3 == "baz" { $2 = "bar" }; 1' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
^b.*z$
または、3番目のフィールドで一致します。
$ awk 'BEGIN { OFS=FS="|" } $3 ~ /^b.*z$/ { $2 = "bar" }; 1' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
...またはミラー(mlr
)、ここで入力は、フィールド区切り文字として使用されるヘッダーなしのCSVファイルとして読み込まれます|
。
$ mlr --csv -N --fs pipe put '$3 == "baz" { $2 = "bar" }' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
または、
$ mlr --csv -N --fs pipe put '$3 =~ "^b.*z$" { $2 = "bar" }' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
awk
あるいは、Millerを使用すると、分離されたフィールドに対してパターンをより簡単かつ安全に一致させることができるという利点があります。 Millerのもう一つの利点は、CSVの引用規則を理解することです。