既存のファイルを直接変更し、「baz」を含む行に対してのみ「foo」を「bar」に置き換えます。

既存のファイルを直接変更し、「baz」を含む行に対してのみ「foo」を「bar」に置き換えます。

以下の 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 -ised以外のコマンドを使用したいと思います。
mobaxterm(OS - Windows)を使用しています。

ベストアンサー1

sedこの状況で使用するのに問題はないと思います。これは仕事に適したツールです。

あなたのコマンドは(与えられたデータに対して)うまく機能します。

$ sed '/baz/s/foo/bar/g' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz

正規表現を使用して、|b行の終わり(行のどこにもない)で始まり、終わるすべての文字列を一致させます。zbaz

$ 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の引用規則を理解することです。

おすすめ記事