8

我有一个文件“changesDictionary.txt”,其中包含(可变数量的)键值字符串对。

例如

"textToSearchFor" = "替换文本"

(字典的格式不重要,可根据需要更改。)

我需要遍历给定目录的内容,包括子目录。对于遇到的每个扩展名为“.txt”的文件,我们在 changesDictionary.txt 中搜索每个键,用替换字符串值替换每个找到的实例。

即搜索和替换多个文件,但使用搜索/替换术语列表而不是单个搜索/替换术语。

我怎么能这样做?(我研究过单个搜索/替换示例,但不明白如何在一个文件中进行多个搜索。)

只要我可以从 Mac OS X 的命令行运行它,实现(bash、perl 等)并不重要。感谢您的帮助。

4

5 回答 5

6

我会将您的 changesDictionary.txt 文件转换为 sed 脚本,使用... sed:

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

请注意,字典中正则表达式或 sed 表达式的任何特殊字符都将被 sed 错误解释,因此您的字典要么只能具有最原始的搜索和替换,要么您需要维护 sed 文件有效的表达。不幸的是,在 sed 中没有简单的方法来关闭正则表达式并仅使用字符串匹配或将您的搜索和替换引用为“文字”。

使用生成的 sed 脚本,使用 findxargs——而不是 find -exec——通过一次处理多个文件,尽快使用 sed 脚本转换文件。

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

请注意-ised 选项“就地”编辑文件,因此请务必进行备份以确保安全,或用于-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. 如果文件都在一个目录中,那么您可以执行以下操作:

    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 回答