ファイルに正しい行がある場合は削除し、残りの行は保持します。エラー処理 - 処理方法

ファイルに正しい行がある場合は削除し、残りの行は保持します。エラー処理 - 処理方法

テキスト処理をどうすれば良い方法なのかよく分からないのでお会いしましょう。

次のファイルがあります。~/.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

通常、grep1つ以上の行がユーザーが提供したREと一致する場合、0(true)が返されます。この-vフラグはこれを反転するため、grepREと一致しないすべての行は成功したと見なされます。この場合、一致が失敗する唯一のケース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複数行の注釈インジケーター(最初の行と最後の行)を削除し、コードが機能していると満足している場合は、両方のインスタンスをに変更します(テキスト戻り値で判断)createonlyFalse

次のようなことができます「ファイル一行、一致」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が投稿した答えと非常によく似ており、sedPerl / Rakuが生成された空白行を削除するという利点があります。 Perl / Rakuの違いについては、2番目のリンクを参照してください。

-iPerlは「内部」置換を実行できますが、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

関連情報