我有一个文件"changesDictionary.txt"包含(可变数量)键值字符串对.
例如
"textToSearchFor"="theReplacementText"
(字典的格式不重要,可根据需要进行更改.)
我需要遍历给定目录的内容,包括子目录.对于扩展名为".txt",我们搜索遇到的每个文件的每个在changesDictionary.txt按键,用替换字符串值替换每个发现的实例.
即搜索和替换多个文件,但使用搜索/替换术语列表而不是单个搜索/替换术语.
我怎么能这样做?(我研究了单个搜索/替换示例,但不了解如何在文件中进行多次搜索.)
只要我可以在Mac OS X中从命令行运行它,实现(bash,perl,无论如何)并不重要.感谢您的帮助.
我将您的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
请注意,-i
sed选项可以"就地"编辑文件,因此请务必进行安全备份,或者使用-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"来改变.
也许你已经考虑了这两个,但我提到因为我已经尝试过你以前做过的事情并没有想到它.我不知道有什么事情可以让你立刻做多次搜索和替换.所以,你需要对它进行编程以便自己做正确的事情.
以下是我要做的基本步骤
复制changesDictionary.txt文件
在它中将"a"="b"替换为等效的sed行:例如(使用$ 1作为文件名)
sed -e's/a/b/g'$ 1
(您可以编写一个脚本来执行此操作,或者只是手动执行,如果您只需要执行此操作并且它不是太大).
如果文件都在一个目录中,那么您可以执行以下操作:
ls*.txt | xargs scriptFromStep2.sh
如果它们位于子目录中,请使用find在所有文件上调用该脚本,例如
找 .-name'*.txt'-exec scriptFromStep2.sh {} \;
这些都不准确,做一些实验以确保你做对了 - 这只是我会用的方法.
(但是,如果可以,只需使用perl,它就会简单得多)