Shell 脚本 - 使用字符串列表搜索和替换多个文件中的文本

问题描述 投票:0回答:5

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

例如

“textToSearchFor”=“theReplacementText”

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

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

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

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

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

unix replace
5个回答
7
投票

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

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

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

对于生成的 sed 脚本,使用 find xargs ——而不是 find -exec ——通过一次处理多个文件来尽快使用 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”。

也许您已经考虑过这两个问题,但我之所以提到,是因为我已经尝试过您之前所做的事情,但没有想到。我不知道有什么可以简单地“做正确的事情”来同时进行多个搜索和替换。因此,您需要对其进行编程,以便自己做正确的事情。


5
投票

复制changesDictionary.txt文件
  1. 其中将“a”=“b”替换为等效的 sed 行:例如(使用 $1 作为文件名)
  2. sed -e 's/a/b/g' $1

    (如果您只需要执行一次并且它不是太大,您可以编写一个脚本来执行此操作,也可以手动执行此操作)。

  3. 如果文件都在一个目录中,那么你可以执行以下操作:
  4. ls *.txt | xargs scriptFromStep2.sh

  5. 如果它们位于子目录中,请使用查找在所有文件上调用该脚本,例如
  6. 找到。 -name '*.txt' -exec scriptFromStep2.sh {} \;

  7. 这些并不准确,请做一些实验以确保正确——这只是我会使用的方法。

(但是,如果可以的话,就用perl吧,会简单很多)


2
投票

https://github.com/tilo/replace_string

特点:

执行多个搜索-替换或查询-搜索-替换操作
  • 搜索替换表达式可以在命令行上给出或从文件中读取
  • 处理多个输入文件
  • 递归地进入目录并对所有文件执行多个搜索/替换操作
  • 用户定义的 Perl 表达式应用于每个输入文件的每一行
  • 可选择以段落模式运行(用于多行搜索/替换)
  • 互动模式
  • 批处理模式
  • 可选择备份文件和备份编号
  • 以 root 身份运行时保留模式/所有者
  • 忽略符号链接、空文件、写保护文件、套接字、命名管道和目录名
  • 可选择替换仅匹配/不匹配给定正则表达式的行
  • 多年来,该脚本已在大型数据集上得到广泛使用。


1
投票


0
投票
ls -1 /script/arq*.sh

做 echo -e“ARQUIVO ${i}” sed -i 's|/$file_path1|/file_path2|g' ${i} 完成

    

© www.soinside.com 2019 - 2024. All rights reserved.