【问题标题】:Replace in one file with value from another file not working properly用另一个文件中的值替换一个文件不能正常工作
【发布时间】:2018-02-19 18:56:37
【问题描述】:

我有两个文件。一个映射文件和一个输入文件。

猫地图.txt

测试:替换

猫输入.txt

test这个词应该被替换,但是testbook这个词不应该被替换 只是因为它有“_test”而被替换。

使用以下命令在文件中查找并将其替换为映射文件中的值。

awk 'FNR==NR{ array[$1]=$2; next } { for (i in array) gsub(i, array[i]) }1' FS=":" map.txt FS=" " input.txt

它的作用是搜索 map.txt 中提到的文本,并在同一个输入文件中替换为“:”之后的单词。 在上面的例子中,“test”用“replace”。

当前结果:

replace这个词应该被替换。但是replacebook这个词不应该仅仅因为它有_replace而被替换。

预期结果:

replace这个词应该被替换。但是testbook这个词不应该仅仅因为它有“_test”而被替换。

所以我需要的是,只有当这个词被发现时,它才必须被替换。如果这个词有任何其他字符,那么它应该被忽略。

感谢任何帮助。

提前致谢。

【问题讨论】:

  • 文件input.txt的内容丢失
  • @Inian 内容在“cat input.txt”下给出。我已经给出了一个示例语句。
  • @lfc_07,您的输入中没有replacebook_test_replace。更新你的问题,它很模糊
  • 对不起。什么是模糊的?全部在输入中。请检查。我正在用替换替换测试。
  • 映射文件所做的是将这个词替换为“:”之后提到的另一个词

标签: bash shell awk sed scripting


【解决方案1】:

for 循环所有单词并在需要的地方替换:

$ awk '
NR==FNR {                     # hash the map file
    a[$1]=$2
    next
}
{
    for(i=1;i<=NF;i++)        # loop every word and if it s hashed, replace it
        if($i in a)           # ... and if it s hashed...
            $i=a[$i]          # replace it
}1
' FS=":" map FS=" " input
The word replace should be replaced.But the word testbook should not be replaced just because it has "_test" in it.

编辑:使用match从字符串中提取单词以保留标点符号:

$ cat input2
Replace would Yoda test.
$ awk '
NR==FNR {                     # hash the map file
    a[$1]=$2
    next
}
{
    for(i=1;i<=NF;i++) {
        # here should be if to weed out obvious non-word-punctuation pairs
        # if($i ~ /^[a-zA-Z+][,\.!?]/)
        match($i,/^[a-zA-Z]+/)       # match from beginning of word. ¿correct?
        w=substr($i,RSTART,RLENGTH)  # extract word
        if(w in a)                   # match in a
            sub(w,a[w],$i)
    }
}1' FS=":" map FS=" " input
Replace would Yoda replace.

【讨论】:

  • 谢谢。它工作正常。但这里还有另一个复杂情况。假设替换词是语句的结尾,它的结尾像“测试”。甚至是句子中间的“测试”。在这种情况下,它不会被替换,因为它后面跟着 .(dot) 或 ,(comma)。在这种情况下有什么解决方案吗?谢谢。
  • @EdMorton 一个人不应该在入睡前两分钟回答...
  • @lfc_07 想更具体一点吗?
  • 删除了一些甚至不在替换列表中的单词。
  • 所以我明白了。能否提供样品?
【解决方案2】:

使用 GNU awk 进行单词边界:

awk -F':' '
NR==FNR { map[$1] = $2; next }
{
    for (old in map) {
        new = map[old]
        gsub("\\<"old"\\>",new)
    }
    print
}
' map input

如果 old 包含正则表达式元字符或转义字符,或者 new 包含 &amp;,则上述操作将失败,但只要两者都使用单词组成字符就可以了。

【讨论】:

  • 有什么方法可以在文件中进行更改?早些时候我使用的是一个衬里,所以将它分配给变量并覆盖文件。在这里不工作,那样。
  • 请忽略,我想通了。谢谢埃德。
猜你喜欢
  • 2018-01-22
  • 2019-03-06
  • 2019-10-27
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 2016-07-12
  • 2012-08-25
  • 1970-01-01
相关资源
最近更新 更多