用Unix文件中的另一个列表替换字符串列表的有效方法是什么?

11 unix bash scripting file-io

假设我有两个字符串列表(列表A和列表B),每个列表中的条目数N完全相同,我希望将所有出现的A的第n个元素替换为B中的第n个元素. Unix中的文件(理想情况下使用Bash脚本).

最有效的方法是什么?

一种效率低下的方法是使N调用" sed s/stringA/stringB/g".

gle*_*man 10

这将在一次通过.它将listA和listB读入awk数组,然后对于每个输出行检查每个单词,如果在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
Run Code Online (Sandbox Code Playgroud)

我假设listA中的字符串不包含空格(awk的默认字段分隔符)


Jon*_*ler 7

拨打一次sed写入sed脚本,另一次使用它?如果你的列表是文件listAlistB,则:

paste -d : listA listB | sed 's/\([^:]*\):\([^:]*\)/s%\1%\2%/' > sed.script
sed -f sed.script files.to.be.mapped.*
Run Code Online (Sandbox Code Playgroud)

我正在做一些关于'单词'不包含冒号或百分号符号的一般性假设,但你可以适应这一点.某些版本的sed上限可以指定的命令数量; 如果这是一个问题,因为你的单词列表足够大,那么你可能必须将生成的sed脚本拆分为应用的单独文件 - 或者更改为使用没有限制的东西(例如Perl).

另一个要注意的项目是变化顺序.如果要交换两个单词,则需要仔细制作单词列表.通常,如果将(1)wordA映射到wordB并将(2)wordB映射到wordC,则重要的是sed脚本是否在映射(2)之前或之后进行映射(1).

显示的脚本对字边界不小心; 您可以通过各种方式对它们进行谨慎处理,具体取决于sed您使用的版本以及构成单词的标准.


AXE*_*abs 5

我需要做类似的事情,最后我根据映射文件生成 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
Run Code Online (Sandbox Code Playgroud)

确保您的 shell 支持与映射中一样多的 sed 参数。

  • 纯 `sed` 和 `bash` 版本: `sed -f &lt;(sed 's/=&gt; //;s# #/#;s#$#/#;s#^#s/#' file.map)东西.txt`。 (2认同)