テキスト処理をどうすれば良い方法なのかよく分からないのでお会いしましょう。
次のファイルがあります。~/.config/mpv/input.conf
他のオプションも含めることができますv disable
。
ファイルからその行を削除するには、次のようにします。
grep -v -q -F 'v disable' input.conf; echo $?
1
ここで - ファイルに現在のような他のコンテンツが含まれていない場合は1(マニュアルページ「選択した行はありません。」と言います1
。シンプルif-statement
。
したがって、$?
コマンドの後に保存し、エラーがある場合は1より大きいことを確認する必要があります。
また、ファイルを適切な場所に変更するのが良いアイデアであるかどうかはわかりません。
grep ... input.conf > input.conf
他の方法があれば教えてください。また、私の提案のいくつかが正しいことを教えてください。
ありがとうございます。
編集1:
目的の動作は、行が存在する状態を切り替えることです(>>
行が存在することを確認してから、簡単な追加で実行します(削除、したがって質問))。
編集2:
許容されるソリューションはPOSIXと互換性がなければなりません。いいえバシズムまたは非POSIXツール。ただし、他の人に役立つ可能性がある非POSIXソリューションを含めることができます。とにかくありがとうございます。
答え1
通常、grep
1つ以上の行がユーザーが提供したREと一致する場合、0(true)が返されます。この-v
フラグはこれを反転するため、grep
REと一致しないすべての行は成功したと見なされます。この場合、一致が失敗する唯一のケースv
は、ソースコードに1行しかあり、REと正確に一致する場合です。
したがって、一致する行を削除し、適用された変更の表示を返すのは少し複雑です。
remove='v disable'
if grep -qxF "$remove" input.conf
then
# Apply the removal, saving a backup
cp -fp input.conf input.conf.bak &&
grep -vxF "$remove" input.conf.bak >input.conf
# Do other things that are relevant if the line was removed
else
# Do things that are relevant if the line was not present
:
fi
の代替案バレンティン・バジラミ終わったコメントから使用ed
その場所からファイルを直接変更します。
if printf '%s\n' '/^v disable/d' wq | ed -s input.conf >/dev/null
then
# Do other things that are relevant if the line was removed
:
else
# Do things that are relevant if the line was not present
:
fi
この場合、一致する文字列はリテラルではなくREとして扱われます。
答え2
使用幸せ(以前のPerl_6)
この回答は@roaimaの素晴らしいコメントに基づいて更新されました。
次のRakuコードは、ファイルに正規表現に一致する行が何回も見つかったかどうかを示します。given
/mode は、when
基本的に Raku の "switch" (または "case") ステートメントです。一致するものが見つかると、変数に保存されます$/
(または)。$<>
~$ raku -e 'my regex RE { ^^ v \s disable $$ };
given "/path/to/original.txt".IO.lines() {
when $_.elems > 0 and none / <RE> / { say "no match"; };
when $_.elems == 1 and / <RE> / { say "one line file, with match"; };
when $_.elems > 1 and / <RE> / { say "multi-line file, with match"; };
default {say "error"; }
};'
したがって、(例えば)when
上記の3番目の声明では、「一致する複数行ファイル」)、ブロックの最後に次のコードを追加できますwhen
。
#`(
spurt("/path/to/original_bak.txt", $_.subst(:global, "$/ "), createonly => True);
unlink("/path/to/original.txt".IO) if "/path/to/original_bak.txt".IO ~~ :e & :f;;
copy("/path/to/original_bak.txt", "/path/to/original.txt", createonly => True)
)
上記の3つのファイル操作に対するエラー処理機能が組み込まれています。スプレー、クラスX::IO::リンク解除とクラスX::IO::コピー。追加できますファイルテスト演算子より多くの側面をテストするための声明です。
このspurt
ステートメントは新しい_bak
ファイルを書き込み、元のunlink
ファイルのリンクを解除し、バックアップファイルを元の名前copy
にコピーして2つのファイルを残します。_bak
複数行の注釈インジケーター(最初の行と最後の行)を削除し、コードが機能していると満足している場合は、両方のインスタンスをに変更します(テキスト戻り値で判断)createonly
。False
次のようなことができます「ファイル一行、一致」when
あるいは、2つのステートメントを1つにまとめるように条件を変更するだけです。 1行形式が気に入らない場合は、スクリプトとして保存し、実行可能にし、cronジョブとして実行するなどの操作を実行できます。
エラー処理を行わない以前の答え(RakuとPerl)は次のとおりです。
幸せ: ~$ raku -ne '.put unless /^v\sdisable$/;' input.conf > tmp_input.conf
真珠: ~$ perl -ne 'print unless /^v disable$/;' input.conf > tmp_input.conf
この答えは@Pankiが投稿した答えと非常によく似ており、sed
Perl / Rakuが生成された空白行を削除するという利点があります。 Perl / Rakuの違いについては、2番目のリンクを参照してください。
-i
Perlは「内部」置換を実行できますが、Rakuは実行できません。ただし、Rakuの制限を回避するためにシェルリダイレクトを使用するように下の3番目のリンクを変更できます(とにかく最初にバックアップを作成してください!)。
注:Rakuは、編集でOPが要求したようにPOSIXに準拠していません。 POSIX以外のアプローチを探しているすべての人にこの回答を残してください。
https://docs.raku.org/言語/5to6-nutshell#given-when
https://unix.stackexchange.com/a/749407/227738
https://unix.stackexchange.com/a/204378/227738
https://raku.org