假设我有两个字符串列表(列表A和列表B),每个列表中的条目数N完全相同,我想用A的第n个元素替换所有出现的A的第n个元素B在Unix中的文件中(理想情况下使用Bash脚本)。
最有效的方法是什么?
效率低下的方法是让N次调用“sed s/stringA/stringB/g
”。
答案 0 :(得分:9)
这将一次完成。它将listA和listB读入awk数组,然后对于linput的每一行,它检查每个单词,如果在listA中找到该单词,则该单词将被listB中的相应单词替换。
awk '
FILENAME == ARGV[1] { listA[$1] = FNR; next }
FILENAME == ARGV[2] { listB[FNR] = $1; next }
{
for (i = 1; i <= NF; i++) {
if ($i in listA) {
$i = listB[listA[$i]]
}
}
print
}
' listA listB filename > filename.new
mv filename.new filename
我假设listA中的字符串不包含空格(awk的默认字段分隔符)
答案 1 :(得分:6)
打电话给sed
编写sed脚本,另一个使用它?如果您的列表位于listA
和listB
文件中,则为:
paste -d : listA listB | sed 's/\([^:]*\):\([^:]*\)/s%\1%\2%/' > sed.script
sed -f sed.script files.to.be.mapped.*
我正在对“单词”进行一些彻底的假设,不包含冒号或百分号,但你可以适应这一点。某些版本的sed
具有可指定的命令数量的上限;如果这是一个问题,因为你的单词列表足够大,那么你可能必须将生成的sed脚本拆分为应用的单独文件 - 或者更改为使用没有限制的东西(例如Perl)。
需要注意的另一个项目是变化顺序。如果要交换两个单词,则需要仔细制作单词列表。通常,如果将(1)wordA映射到wordB并将(2)wordB映射到wordC,则重要的是sed脚本是否在映射(2)之前或之后进行映射(1)。
显示的脚本对字边界不小心;您可以通过各种方式对其进行审核,具体取决于您使用的sed
版本以及您构成单词的标准。
答案 2 :(得分:2)
我需要做类似的事情,然后根据地图文件生成sed命令:
$ cat file.map
abc => 123
def => 456
ghi => 789
$ cat stuff.txt
abc jdy kdt
kdb def gbk
qng pbf ghi
non non non
try one abc
$ sed `cat file.map | awk '{print "-e s/"$1"/"$3"/"}'`<<<"`cat stuff.txt`"
123 jdy kdt
kdb 456 gbk
qng pbf 789
non non non
try one 123
确保您的shell支持与您在地图中一样多的sed参数。
答案 3 :(得分:1)
这对Tcl来说相当简单:
set fA [open listA r]
set fB [open listB r]
set fin [open input.file r]
set fout [open output.file w]
# read listA and listB and create the mapping of corresponding lines
while {[gets $fA strA] != -1} {
set strB [gets $fB]
lappend map $strA $strB
}
# apply the mapping to the input file
puts $fout [string map $map [read $fin]]
# if the file is large, do it line by line instead
#while {[gets $fin line] != -1} {
# puts $fout [string map $map $line]
#}
close $fA
close $fB
close $fin
close $fout
file rename output.file input.file
答案 4 :(得分:1)
您可以在bash
中执行此操作。将列表放入数组中。
listA=(a b c)
listB=(d e f)
data=$(<file)
echo "${data//${listA[2]}/${listB[2]}}" #change the 3rd element. Redirect to file where necessary
答案 5 :(得分:-1)
使用tr(1)(翻译或删除字符):
cat file | tr 'abc' 'XYZ' > file_new
mv file_new file