以下の 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の引用規則を理解することです。
答え2
awk
次のように使用しますgsub()
。
awk '/baz$/ {gsub("foo", "bar")};1' food.txt
/baz$/
必要に応じて、正規表現パターンを代わりに使用して一致させることができます。パターンが一致したら、
gsub()
必要な文字列を置き換えます。
内部編集のために、最新バージョンのGNU awk
(> = 4.1.0)には内部修正オプションがあります。
awk -i inplace '/baz$/ {gsub("foo", "bar")};1' food.txt
sponge
それ以外の場合は、GNUを使用するかmoreutils
一時ファイルを使用できます。
awk '/baz$/ {gsub("foo", "bar")};1' food.txt >temp_food.txt && \
mv temp_food.txt food.txt
例:
$ cat file.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|foo|baz
$ awk '/baz$/ {gsub("foo", "bar")};1' file.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
答え3
sed -i
必要なものを正確に実行するのを使用したくない理由はわかりませんが、代替案は次のとおりですperl
。
$ perl -pe 's/foo/bar/g if /b*z/' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
これは、-pe
「スクリプトを適用した後、入力ファイルの各行を印刷します。
-i
以下を使用して、その場所でファイルを編集できます。
perl -i -pe 's/foo/bar/g if /b*z/' food.txt
また、正規表現はb*z
「0以上に一致し、b
後にaが続くことを意味します。andをz
省略して一致し、一致のみするため、ここで機能します。b*z
つまり、anyは0の例の後にaになるため、どんなものとも一致します。 I 使いたいのは b.*z(ab の後に 0 個以上の文字が来て az が来ます)と考えてください。bar
b
a
z
z
z
b
z
perl -i -pe 's/foo/bar/g if /b.*z/' food.txt
答え4
自動テキスト編集のための実際に最適なツールは次のとおりです。ex
。
直接電話することも可能でしょうがex
、探してみるとMobaXtermから電話する必要がありますvim -e
。
自動編集を行う最良の方法はMobaXtermから(他の* nixシステムでも機能します)は次のとおりです。
printf '%s\n' 'g/b.*z/s/foo/bar/g' x | vim -es food.txt
POSIXと完全に互換性があるようにするには、次のように変更してください。
printf '%s\n' 'g/b.*z/s/foo/bar/g' x | ex -s food.txt
ただし、このex
コマンドを呼び出すと、MobaXtermで正しく機能しなくなる可能性があります(私がインストールした場合は動作しませんでした)。そのバージョンが失敗した場合は、vim -es
このバージョンのコマンドを試してください。ex