検索とsed(検索と削除)

検索とsed(検索と削除)

その中には複数のサブフォルダとファイルがあるフォルダがあります。サブフォルダの名前とサブフォルダ内のファイルのパターンを含むCSVファイルもあります。

私がしたいのは、デフォルトのフォルダ内のwhileループを使用してCSVファイルを読み込みますsed。私はbashUnixで次のシェルスクリプトを使います:

IFS=","
while read f1 f2
do
 find $f2/ -name vcs*.pv -exec sed -i '/$f1/d' {} +
done > export.csv

間違い:

find: 'ap01\r/': No such file or directory.

CSVファイル:

S2AEC67X1,ap01

値を正しく読み込んでいますが、f2残りは行いません。すべてのサブフォルダーと共に、デフォルトのディレクトリにCSVファイルを保存します。

答え1

これ:ap01\r

あることを示します。入力する文字列の後にapi01。 CSVファイルから削除してみてください。

アップデート:@RomanPerekhrestのコメントも読んでください。ループ内でを>aに変更する必要があります(実際にそうする必要がある場合)。<while使用サイクルwhileですが、それは完全に別の議論です! )。

答え2

この質問のコードと入力ファイルにはいくつかの問題があります。

  1. 入力ファイルの各行には、\r明らかに末尾のキャリッジリターン()があります。これは、WindowsコンピュータでヒットがDOSテキストファイルとして生成されたためです。これらのキャリッジリターンを削除する一般的な方法は、dos2unixファイルから実行することです。たとえば、質問を参照してください。"^M" とは何か、その修復方法は?

  2. すべての変数拡張は二重引用符で囲む必要があります。コマンドは、$f2引用符なしでディレクトリのパス名を使用します。スペースが含まれていると失敗します$f2

  3. 一重引用符は、シェルが変数を拡張するのを防ぎます。これはsed、スクリプトがリテラル正規表現に一致する行を見つけることを意味します$f1。この正規表現は行$の終わりのみと一致し、行の終わりは一致しないため、絶対一致しません。次に、f1同じ行に文字を含めます。。二重引用符でスクリプトを編集すると、シェルが呼び出す前に変数を拡張しますsed$f1sed

  4. パターンはオプションの引数でなけれvcs*.pvばなりませんが、引用符がないため、ワイルドカードパターンと一致する現在のディレクトリのすべての名前に展開されます。したがって、現在のディレクトリにという名前のファイルがある場合は、そのファイルが呼び出され、その名前のファイルのみが検索されます。現在のディレクトリに複数の一致する名前がある場合は、不明なオプションについて文句を言うことができます。-namefindvcs-test.pvfind-name vcs-test.pvfind

  5. ファイルexport.csvは出力されます(ループ内で出力が発生する前に空になります)。何度も何度も読もうと思うかもしれません。これに>はに変更することが含まれます<

スクリプトが修正されました:

while IFS=',' read f1 f2; do
    find "$f2" -type f -name 'vcs*.pv' -exec sed -i "/$f1/d" {} +
done <export.csv

誤ってディレクトリ名を取得したくないので、コマンドライン-type fにも追加しました。私はまた変数を設定findするためにこれをしましたIFSただコマンドのためにread


これはすべてのファイルが配置されている上記のバリエーションです。まっすぐCSVファイルから名前を読み取った最上位ディレクトリの下:

while IFS=',' read dir pattern; do
    for name in "$dir"/vcs*.pv; do
        test -f "$name" && sed -i "s/$pattern/d" "$name"
    done
done <export.csv

これの利点は、あなたがそれを避けることができるということですfind。欠点は、sedファイルごとに1回呼び出す必要があることです(通常、何百ものファイルがないと問題になりません)。

以下は、上記のバリエーションで行を削除します。ひもCSVファイルから読み込みます。違いは、上記のコードスニペットがパターンを次のように解釈することです。正規表現、固定文字列ではありません。文字列に正規表現(たとえば、など)で「特殊」と解釈される文字が含まれている場合、.これは*重要[です。]

while IFS=',' read dir string; do
    for name in "$dir"/vcs*.pv; do
        [ ! -f "$name" ] && continue
        grep -v -F -e "$string" "$name" >"$name.tmp" && mv -f "$name.tmp" "$name"
    done
done <export.csv

関連情報