50

単刀直入に言うと、grep/find/sed/awk を使用して特定の文字列 (数字で終わる) を照合し、その数字を 1 ずつ増やす方法を考えています。最も近いのは、1 を連結して主なポイントは単に値を変更することであるため、最後(これで十分に機能します)。これが私が現在行っていることです:

find . -type f | xargs sed -i 's/\(\?cache_version\=[0-9]\+\)/\11/g'

数字を増やす方法がわからなかったので、全体をキャプチャして「1」を追加しました。以前、私は次のようなものを持っていました:

find . -type f | xargs sed -i 's/\?cache_version\=\([0-9]\+\)/?cache_version=\11/g'

少なくとも、必要なものをキャプチャする方法を理解しています。

これが何のためにあるのかを説明する代わりに、私が何をしたいのかを説明します。現在のディレクトリに基づいて、任意のファイル内のテキストを再帰的に検索する必要があります (重要ではありません。任意のディレクトリである可能性があるため、後で構成します)。次に、その番号をインクリメントし、ファイル内で置き換えます。

現在、上記のものは機能していますが、最後に見つかった番号をインクリメントできないだけです。将来の値が「11」、「111」、「1111」、「11111」などにならないように、「1」を追加する代わりにインクリメントできるとよいでしょう。

私は何十もの記事/説明を見てきましたが、多くの場合、提案は を使用することですがawk、私の人生ではそれらを混在させることはできません。awk実際には何も置き換えないを使用することに最も近いのは次のとおりです。

grep -Pro '(?<=\?cache_version=)[0-9]+' . | awk -F: '{ print "match is", $2+1 }'

sed最後に a をパイプして元のファイル名を渡し、sedファイル名とインクリメントされた番号(からawk)、または必要なものを何でも持つことができる方法があるかどうか疑問に思ってxargsいます。

技術的には、この数値は重要ではありません。この置換は、主にそこに新しい番号があることを確認するためのものであり、最後の番号とは 100% 確実に異なります。したがって、この質問を書いているときに、システム時間を使用する方がよいことに気付きました-エポックからの秒数(後続の「同一の」リクエストのキャッシュを排除するためにAJAXでよく使用される手法)。私はこれで終わりました、そしてそれは完璧に思えます:

CXREPLACETIME=`date +%s`; find . -type f | xargs sed -i "s/\(\?cache_version\=\)[0-9]\+/\1$CXREPLACETIME/g"

(何らかの理由で数秒に及ぶ場合に備えて、最初に値を保存して、すべてのファイルが同じ値になるようにします)

しかし、一致した数を増やすという元の質問を知りたいです。簡単な解決策はそれをbashスクリプトにすることだと思いますが、それでも、すべてのファイルを再帰的にループし、その内容が一致するかどうかを確認してから置き換えるよりも簡単な方法があると思いました。 ...他の多くのロジックはありません。他のファイルなどに書き込みたくないだけです- sed「i」オプションのように、その場で行う必要があります。

4

5 に答える 5

69

ファイルを見つけることは、あなたにとって難しい部分ではないと思います。したがって、+1 の計算を行うという点に進みます。gnu sedがある場合は、次の方法で実行できます。

sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge' file

例を見てみましょう:

kent$  cat test 
ello
barbaz?cache_version=3fooooo
bye

kent$  sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge' test     
ello                                                                             
barbaz?cache_version=4fooooo
bye

必要に応じて -i オプションを追加できます。

編集

/e一致した部分を外部コマンドに渡し、実行結果で置換することができます。Gnu sed のみ。

この例を参照してください:外部コマンド/ツールechobc使用されています

kent$  echo "result:3*3"|sed -r 's/(result:)(.*)/echo \1$(echo "\2"\|bc)/ge'       

出力を与えます:

result:9

cut、sed (再び)、awk など、他の強力な外部コマンドを使用できます。

于 2013-01-15T23:32:48.220 に答える
9

このperlコマンドは、現在のディレクトリ内のすべてのファイルを検索し (トラバースせずにFile::Find、より複雑なタスクにはモジュールまたは類似のものが必要になります)、一致する行の番号を増やしますcache_version=/e置換部分を評価する正規表現のフラグを使用します。

perl -i.bak -lpe 'BEGIN { sub inc { my ($num) = @_; ++$num } } s/(cache_version=)(\d+)/$1 . (inc($2))/eg' *

file次のデータを使用して現在のディレクトリでテストしました:

hello
cache_version=3
bye

ls -1元のファイル ( )をバックアップします。

file
file.bak

そしてfile今:

hello
cache_version=4
bye

あなたが探しているものに役立つことを願っています。


File::Findディレクトリのトラバースに使用するUPDATE 。引数として受け入れ*ますが、 で見つかったものと一緒に破棄しますFile::Find。検索を開始するディレクトリは、スクリプトの現在の実行です。行にハードコーディングされていますfind( \&wanted, "." )

perl -MFile::Find -i.bak -lpe '

    BEGIN { 
        sub inc { 
            my ($num) = @_; 
            ++$num 
        }

        sub wanted {
            if ( -f && ! -l ) {  
                push @ARGV, $File::Find::name;
            }
        }

        @ARGV = ();
        find( \&wanted, "." );
    }

    s/(cache_version=)(\d+)/$1 . (inc($2))/eg

' *
于 2013-01-15T23:16:07.210 に答える
9

純粋なsedバージョン:

このバージョンは、他のコマンドや環境変数に依存しません。明示的なキャリーを使用します。キャリーには@記号を使用しますが、必要に応じて別の名前を使用できます. 入力ファイルに存在しないものを使用してください。最初にSEARCHSTRING<number>@ を見つけてそれに追加します。保留中の桁上げがある (つまり、その後に桁上げ記号がある: [0-9]@) 数字をインクリメントして繰り返します。最後に、得られたが、まだ桁に追加されていないキャリーは 1 に置き換えられます。

sed "s/SEARCHSTRING[0-9]*[0-9]/&@/g;:a {s/0@/1/g;s/1@/2/g;s/2@/3/g;s/3@/4/g;s/4@/5/g;s/5@/6/g;s/6@/7/g;s/7@/8/g;s/8@/9/g;s/9@/@0/g;t a};s/@/1/g" numbers.txt
于 2015-09-29T10:27:29.960 に答える
3

これは醜いですが (私は少し錆びています)、sed の使用を開始します。

orig="something1" ;
text=`echo $orig | sed "s/\([^0-9]*\)\([0-9]*\)/\1/"` ;
num=`echo $orig | sed "s/\([^0-9]*\)\([0-9]*\)/\2/"` ;
echo $text$(($num + 1))

元のファイル名 ( ) が「something1」の場合、sed はテキスト部分と数値部分をとに$orig分割し、最終セクションでこれらを組み合わせて数字を増やして.$text$numsomething2

ファイル名に数字が含まれている場合や末尾に数字がない名前の場合は考慮されていないため、ほんの始まりに過ぎませんが、sed を使用するという当初の目標に役立つことを願っています。

これは、バッファーを使用することで sed 内で実際に単純化できると思います (sed は再帰的に動作する可能性があります) が、私はその側面に本当に慣れていません。

于 2013-01-15T23:26:37.813 に答える