8

キーと値の文字列のペア (可変数) を含むファイル「changesDictionary.txt」があります。

例えば

"textToSearchFor" = "theReplacementText"

(辞書の形式は重要ではなく、必要に応じて変更してください。)

サブディレクトリを含む、特定のディレクトリの内容を反復処理する必要があります。拡張子「.txt」を持つファイルごとに、changesDictionary.txt 内のキーを検索し、見つかった各インスタンスを置換文字列値に置き換えます。

つまり、複数のファイルに対する検索と置換ですが、単一の検索/置換用語ではなく、検索/置換用語のリストを使用します。

どうすればこれを行うことができますか? (単一の検索/置換の例を調べましたが、ファイル内で複数の検索を行う方法がわかりません。)

実装 (bash、perl など) は、Mac OS X のコマンド ラインから実行できる限り重要ではありません。助けてくれてありがとう。

4

5 に答える 5

6

私はあなたのchangesDictionary.txtファイルをsedスクリプトに変換します...sed:

$ sed -e 's/^"\(.*\)" = "\(.*\)"$/s\/\1\/\2\/g/' \
      changesDictionary.txt  > changesDictionary.sed

注意:辞書内の正規表現またはsed式の特殊文字は、sedによって誤って解釈されるため、辞書に含めることができるのは最も原始的な検索と置換のみであるか、sedファイルを次のように維持する必要があります。有効な式。残念ながら、sedで正規表現をシャットオフして文字列照合のみを使用するか、検索と置換を「リテラル」として引用する簡単な方法はありません。

結果のsedスクリプトで、 find-execではなくfindxargsを使用して、一度に複数のファイルを処理することにより、sedスクリプトを使用してファイルをできるだけ早く変換します。

$ find somedir -type f -print0 \
   | xargs -0 sed -i -f changesDictionary.sed

sed-iオプションはファイルを「インプレース」で編集するため、安全のために必ずバックアップを作成するか、-i~チルダバックアップの作成に使用してください。

最後に、検索と置換を使用すると、意図しない結果が生じる可能性があります。他の検索のサブストリングである検索はありますか?これが例です。

$ cat changesDictionary.txt
"fix" = "broken"
"fixThat" = "Fixed"
$ sed -e 's/^"\(.*\)" = "\(.*\)"$/s\/\1\/\2\/g/' changesDictionary.txt  \
   | tee changesDictionary.sed
s/fix/broken/g
s/fixThat/Fixed/g
$ mkdir subdir
$ echo fixThat > subdir/target.txt
$ find subdir -type f -name '*.txt' -print0 \
   | xargs -0 sed -i -f changesDictionary.sed
$ cat subdir/target.txt
brokenThat

「fixThat」は「Fixed」または「brokenThat」になっている必要がありますか?sedスクリプトの注文事項。同様に、検索と置換は複数回検索して置換できます。「a」を「b」に変更すると、後で別の検索と置換によって「b」から「c」に変更される場合があります。

おそらくあなたはすでにこれらの両方を検討しているかもしれませんが、私はあなたが以前にやっていたことを試したが、それについて考えていなかったので言及します。一度に複数の検索と置換を行うために単に正しいことをするものは何も知りません。したがって、自分で正しいことを行うようにプログラムする必要があります。

于 2009-03-16T19:07:59.500 に答える
5

これが私が行う基本的な手順です

  1. changesDictionary.txt ファイルをコピーします。
  2. その中で、"a"="b" を同等の sed 行に置き換えます: 例 (ファイル名に $1 を使用)

    sed -e 's/a/b/g' $1

    (これを行うためのスクリプトを作成するか、これを一度だけ行う必要があり、大きすぎない場合は、手動で行うことができます)。

  3. ファイルがすべて 1 つのディレクトリにある場合は、次のようなことができます。

    ls *.txt | xargs scriptFromStep2.sh

  4. それらがサブディレクトリにある場合は、find を使用してすべてのファイルでそのスクリプトを呼び出します。

    探す 。-name '*.txt' -exec scriptFromStep2.sh {} \;

これらは正確ではありません。いくつかの実験を行って、正しいことを確認してください。これは、私が使用するアプローチにすぎません。

(ただし、可能であれば、perl を使用するだけで、はるかに簡単になります)

于 2009-03-16T00:31:20.030 に答える
2

Perl で書かれたこのツールを使用してください - かなり多くの付箋がついています - 古いものですが、良いものです:

http://unixgods.org/~tilo/replace_string/

特徴:

  • 複数の検索-置換またはクエリ-検索-置換操作を行う
  • 検索置換式は、コマンド ラインで指定するか、ファイルから読み取ることができます
  • 複数の入力ファイルを処理する
  • 再帰的にディレクトリに降りて、すべてのファイルに対して複数の検索/置換操作を実行します
  • ユーザー定義のPerl式が各入力ファイルの各行に適用されます
  • オプションで段落モードで実行 (複数行の検索/置換用)
  • 対話モード
  • バッチモード
  • オプションでバックアップ ファイルとバックアップの番号付け
  • root として実行するときにモード/所有者を保持する
  • シンボリック リンク、空のファイル、書き込み保護されたファイル、ソケット、名前付きパイプ、およびディレクトリ名を無視する
  • オプションで、指定された正規表現に一致する/一致しない行のみを置換します

このスクリプトは、長年にわたって大規模なデータ セットで非常に広範囲に使用されてきました。

于 2011-03-26T04:10:16.830 に答える
1
#!/bin/bash
f="changesDictionary.tx"
find /path -type f -name "*.txt" | while read FILE 
do
    awk 'BEGIN{ FS="=" }
    FNR==NR{ s[$1]=$2;  next }
    {
       for(i in s){      
        if( $0 ~ i ){ gsub(i,s[i]) }
       }
       print $0
    }' $f $FILE  > temp
    mv temp $FILE
done
于 2009-08-06T14:22:15.563 に答える
0

for i in ls -1 /script/arq*.sh do echo -e "ARQUIVO ${i}" sed -i 's|/$file_path1|/file_path2|g' ${i} done

于 2022-01-27T19:11:33.673 に答える