端的に言うと、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'
だから、少なくとも必要なものをキャプチャする方法は理解しています。
これが何のためにあるのかを説明する代わりに、私がこれをどうしたいのかを説明します。これは、現在のディレクトリ (重要ではありません。任意のディレクトリでよいので、後で設定します) に基づいて、任意のファイル内で、数値を持つ "?cache_version=" に一致するテキストを再帰的に検索します。次に、その数値を増分して、ファイル内で置き換えます。
現時点では、上記のものは機能していますが、最後に見つかった数字を増やすことができません。将来の値が「11」、「111」、「1111」、「11111」などにならないように、「1」を追加するのではなく、増やすことができればもっと良いでしょう。
私は何十もの記事や説明を読んできましたが、多くの場合、 を使用することが提案されていますawk
が、どうしてもそれらを混在させることはできません。 を使用することに最も近いのはawk
、実際には何も置き換えない です。
grep -Pro '(?<=\?cache_version=)[0-9]+' . | awk -F: '{ print "match is", $2+1 }'
sed
最後に をパイプして元のファイル名を渡し、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" オプションのように、その場で実行する必要があります。
ベストアンサー1
ファイルを探すのはそれほど難しいことではないと思います。そこで、+1の計算をします。GNU セッド次のように実行できます。
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 のみ。
この例を参照してください: 外部コマンド/ツールecho
がbc
使用されています
kent$ echo "result:3*3"|sed -r 's/(result:)(.*)/echo \1$(echo "\2"\|bc)/ge'
出力は次のようになります。
result:9
cut、sed (再び)、awk などの他の強力な外部コマンドを使用することもできます...