我使用以下命令
awk -f script.sh dictionary.txt "test.txt" >> "test2.txt"
替换.txt中的某些字符。我的脚本如下:
NR == FNR {
rep[$1] = $2
next
}
{
for (key in rep) {
gsub(key, rep[key])
}
print
}
这是我的字典:
I 0:maj[ |]*
i 0:min[ |]*
bII 1:maj[ |]*
II 2:maj[ |]*
ii 2:min[ |]*
bIII 3:maj[ |]*
III 4:maj[ |]*
iii 4:maj[ |]*
IV 5:maj[ |]*
iv 5:min[ |]*
V 7:maj[ |]*
v 7:min[ |]*
bVI 8:maj[ |]*
VI 9:maj[ |]*
vi 9:min[ |]*
bVII t:maj[ |]*
VII e:maj[ |]*
vii e:min[ |]*
我面临两个问题:
1)II(或ii,III,VI等)不是作为一个独立的实体读取,而是作为两次读取I.我如何指定我的脚本中第一列中的所有内容都应该被读作& #34;块"的人物。我尝试使用(),[],"&#34 ;;什么接缝都没用。我可以使用i {2}来区分ii和i,但我不能像vi这样做。
2)第二列中的空格字符会产生一些问题。我试图逃避它,但它不会工作。
任何技巧?
[edit]这里是.txt的样本
I ii V V
I II V V
I ii IV V
I ii III IV
I ii vi IV
I ii iii IV
I II IV V
I IV I ii
i ii V V
i ii V V
i II V V
i ii iv V
i ii IV V
i ii vi IV
答案 0 :(得分:3)
以下是其示例输出的替代方案:
$ awk 'NR==FNR{k=$1; $1=""; r[k]=substr($0,2);next} {for (i=1;i<=NF;i++){if ($i in r) {$i=r[$i]}}} {print}' dictionary.txt "test.txt"
0:maj[ |]* 2:min[ |]* 7:maj[ |]* 7:maj[ |]*
0:maj[ |]* 2:maj[ |]* 7:maj[ |]* 7:maj[ |]*
0:maj[ |]* 2:min[ |]* 5:maj[ |]* 7:maj[ |]*
0:maj[ |]* 2:min[ |]* 4:maj[ |]* 5:maj[ |]*
0:maj[ |]* 2:min[ |]* 9:min[ |]* 5:maj[ |]*
0:maj[ |]* 2:min[ |]* 4:maj[ |]* 5:maj[ |]*
0:maj[ |]* 2:maj[ |]* 5:maj[ |]* 7:maj[ |]*
0:maj[ |]* 5:maj[ |]* 0:maj[ |]* 2:min[ |]*
0:min[ |]* 2:min[ |]* 7:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 7:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:maj[ |]* 7:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 5:min[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 5:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 9:min[ |]* 5:maj[ |]*
此方法处理字典值,其中包含空格,或者即使它们中有多个空格。
每个部分,一次一个:
NR==FNR{k=$1; $1=""; r[k]=substr($0,2);next}
这将从r
文件创建字典dictionary.txt
。关键是第一个领域。该值是删除第一个字段后该行剩余的值。删除第一个字段分两步完成:(a)将$1
设置为空字符串,(b)使用$1
删除现在为空的substr
后面的空格功能
{for (i=1;i<=NF;i++){if ($i in r) {$i=r[$i]}}}
这会依次通过每个字段进行替换。由于输入现在被视为字段而不是字符,因此ii
等字段不会被误认为连续两个i
。
{print}
打印带有替换的整行。
gsub
您遇到的问题是结果取决于从字典中检索密钥的顺序:
for (key in rep) {
gsub(key, rep[key])
}
例如,如果在i
之前检索到ii
,则输入ii
被视为连续两次i
。
答案 1 :(得分:1)
不要使用gsub
,只需浏览每个字段并进行直接交换:
NR == FNR {
rep[$1] = $2 " " $3
next
}
{
for (i=1; i<=NF; ++i) {
if ($i in rep) $i = rep[$i]
}
print
}
或者如果你喜欢单行:
awk 'NR==FNR{rep[$1]=$2" "$3;next}{for(i=1;i<=NF;++i)if($i in rep)$i=rep[$i]}1' dictionary.txt test.txt
您的方法存在的问题是ii
确实与正则表达式/i/
以及/ii/
匹配,因此gsub
会在数组中首先遇到它所遇到的替换。使用这种方法,您可以交换完全匹配的密钥的值。请注意,我也更改了rep
的分配,以处理[ |]*
之间的空格,因为awk将这些视为两个不同的字段。
输出:
0:maj[ |]* 2:min[ |]* 7:maj[ |]* 7:maj[ |]*
0:maj[ |]* 2:maj[ |]* 7:maj[ |]* 7:maj[ |]*
0:maj[ |]* 2:min[ |]* 5:maj[ |]* 7:maj[ |]*
0:maj[ |]* 2:min[ |]* 4:maj[ |]* 5:maj[ |]*
0:maj[ |]* 2:min[ |]* 9:min[ |]* 5:maj[ |]*
0:maj[ |]* 2:min[ |]* 4:maj[ |]* 5:maj[ |]*
0:maj[ |]* 2:maj[ |]* 5:maj[ |]* 7:maj[ |]*
0:maj[ |]* 5:maj[ |]* 0:maj[ |]* 2:min[ |]*
0:min[ |]* 2:min[ |]* 7:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 7:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:maj[ |]* 7:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 5:min[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 5:maj[ |]* 7:maj[ |]*
0:min[ |]* 2:min[ |]* 9:min[ |]* 5:maj[ |]*