web-dev-qa-db-ja.com

正規表現が含まれている場合、sedのファイルをスキップするにはどうすればよいですか?

私は現在、次の 簡略化されたコマンド から末尾の空白を削除およびファイルの最後に改行を追加必要に応じて使用しています。

find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+

すぐにわかるように、これには2つの問題があります。変更されるバイナリファイルと、ファイルの末尾に␍␊行区切り記号で改行が追加されます。これらの変更は、git guiなどでコミットするときに簡単に元に戻したりスキップしたりできますが、元に戻す量を最小限に抑えたい*と思います。そのために:

any行がsedの正規表現と一致する場合、wholeファイルをスキップする方法はありますか?

*␀文字のないバイナリファイルが存在する可能性があること、および意図的に改行または␀が混在するファイルが存在する可能性があることを認識しています。しかし、私は最小限の人間の介入を必要とする解決策を探しています。 I couldおそらく、操作したいすべてのファイル拡張子をリストしますが、それは非常に長いリストであり、絶えず見直す必要があり、名前の衝突のためにそれでも可能です。そのバイナリファイルはすり抜けます。

複雑 回避策

while IFS= read -r -d '' -u 9
do
    if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]]
    then
        sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' -- "$REPLY"
    else
        echo "Skipping $REPLY" >&2
    fi
done 9< <(find . -type f -print0)
4
l0b0

バイナリファイルとは何かについてgitの観点を信頼している場合は、git grepを使用して非バイナリファイルのリストを取得できます。 t.cppがテキストファイルであり、lsがバイナリであると仮定すると、両方ともチェックインされます。

$ ls
t.cpp ls
$ git grep -I --name-only -e ''
t.cpp

-Iオプションの意味:

-I
バイナリファイルのパターンと一致しないでください。

これをsed式と組み合わせるには:

$ git grep -I --name-only -z -e '' | \
       xargs -0 sed -i.bk -e 's/[ \t]\+\(\r\?\)$/\1/;$a\'

-z/xargs -0は、奇妙なファイル名を支援します。)

その他の便利なオプションについては、git grepのマニュアルページを確認してください。--no-indexまたは--cachedは、操作するファイルのセットに応じて役立つ場合があります。

2
Mat

Sedの正規表現に一致する行がある場合にファイル全体をスキップする方法はありますか?

はいあります。

# test case for skipping file if a sed regex match succeeds

echo 'Hello, world!' > hello_world.txt
cat hello_world.txt
ls -li hello_world.txt

sed -i -e '/.*Hello.*/{q;}; s/world/WORLD/g' hello_world.txt # skips file
sed -i -e '/.*HeLLo.*/{q;}; s/world/WORLD/g' hello_world.txt
2
vron

これは、引数(ファイル名である必要があります)を反復処理し、改行で終わらないすべてのファイルに改行を追加するPerlスクリプトです。 nullバイトを含むファイルはスキップされます。すでに改行で終わっているファイルは変更されません。 CRを含むファイルにはCRLFが追加され、その他のファイルにはLFのみが追加されます。テストされていません。

#!/usr/bin/env Perl
foreach my $f (@ARGV) {
    open F, "<", $f or die;
    my $last = undef;
    my $cr = 0;
    while (<>) {if (/\0/) {undef $last; break} $last = $_; ++$cr if /\r$/}
    close F;
    if (defined $last && $last !~ /\n\Z/) {
        open F, ">>", $f or die;
        print($cr ? "\r\n" : "\n");
        close F or die;
    }
}