重新使用sed流来追加字符串

分享于 

6分钟阅读

电脑

  繁體 雙語

问题:

TL; DR:需要在sed中重用流,以便将提取的字符串添加到当前行的结尾。

我有一个脚本使用sed提取子字符串,并使用此子字符串的名称命令进行复制。

我尝试了一些这样的事情,但 sed -e 分别解析每一行,reinvoking rtc对当前所分析的每行重新读取所有行:

下面的一行将输出提取的字符串:


cat hello.txt | sed -e 's/.*search_start(.*)search_end*/1/' | xargs -I@"echo./@"



此行创建一个字符串,该字符串为文件夹 location 添加了复制命令:


cat hello.txt | sed -e 's/(^)/copy/; s/$/./location/;'



但是,我希望在这里添加这些,以便在这里处引用 extracted_str 搜索字符串来代替 location 文件夹。 所以,我需要像这样的( 对于每一行):


copy input_sed_line extracted_str




回答 1:

如果我理解正确的问题,你需要额外出现整行以及它的任何sed摘录。 sed 可以用 p 打印整个代码行,所以这是可能的:


 <hello.txt sed -e 'p; s/.*search_start(.*)search_end.*/1/' | xargs -d 'n' -n 2 copy --



注释:

  • 无论 copy 是( 你是指 cp) 。
  • 我假设 copy 能理解 -- ( 选项标记的结尾) 。
  • 我修正了 cat 无用的用法。
  • 我认为 search_end* 应该是 search_end.*
  • POSIX不需要 xargs-d-n 选项。 查看操作系统中的man 1 xargs 以判断是否可以使用它们。 这里-d'n'将换行符指定为分隔符,-n 2告诉xargs每个副本使用两个输入项。 -n,如果支持的话,可能是有限的。

以上可能在许多情况下都有效,但如果我是你,我会使用一个shell和它内置的读取。 它是 true 一个不应该循环 read 解析文本sedawk 等是一般的工具。 然而,你的目标不仅仅是分析文本。 你的目标是制作和运行命令。 像 sh 或者 bash 这样的shell 是运行命令的正确工具。


#!/bin/sh



while IFS= read -r wholeline; do


 target="$(printf '%sn'"$wholeline" | sed -e 's/.*search_start(.*)search_end.*/1/')"


 copy --"$wholeline""$target"


done <hello.txt



代码为每一行运行一个单独的sed 进程。 在你的情况下,可以很容易地避免这种情况:


#!/bin/sh



while IFS= read -r wholeline; do


 target="${wholeline##*search_start}" # removing prefix


 target="${target%%search_end*}" # removing postfix


 copy --"$wholeline""$target"


done <hello.txt



可以使用 awk 来执行( 几乎):


 <hello.txt awk '{


 target=$0


 sub(/.*search_start/,"",target)


 sub(/search_end.*/,"",target)


 cmdline="copy -- '"'"'"$0"'"' '"'"target"'"'"'"


 system(cmdline)


 }'



但存在以下问题:

  • 引用狂热。有三个级别需要引用并解释它们: 调用 awk的原始 shell,awk 本身,由 system() 调用的shell 。 你可以通过构建 awk 脚本( 像 #!/usr/bin/awk 这样的东西) 来消除第一个级别。 仍然很麻烦。我甚至不确定我把这些引号放在了我想要的。
  • cmdline 作为字符串传递,然后解析为解析,而不是作为参数的array 。 如果输入包含文字 ' 字符,那么事情会断开,输入的某些部分可以能会被执行( 代码注入) 。
  • system(cmdline) 调用 sh,为每一行增加额外的shell 。 你可以用 print cmdline 代替,然后把整个输出输出到一个 sh ( 。或者保存到文件以便以后解析) 。 这将减少进程的数量,但前面的问题将继续存在: 文本输出将被解析更快或者更晚。
  • 从我的经验来看,这些问题并不局限于 awk 。 如果要使用任何工具以基于任意输入的参数运行外部命令,请注意它是否传递字符串( 被 sh 或者任何东西解析),或者使用严格定义的参数类型生成新进程。 比如 find -exec 执行后一个( 或者至少是 find的通用实现) 。

    结论:

    • xargs 可能缺少有用的选项。
    • 文本处理工具在处理文本时比shell更好,但在运行外部命令时通常更糟糕。

    出于这个原因,我认为 shell 循环在这里至少是合理的。 你仍然应该读好的答案的已经链接的问题。 注意我的shell script 没有遵循你能找到的所有提示。


回答 2:

为什么不?


location=$(cat hello.txt | sed -e 's/.*search_start(.*)search_end*/1/' | xargs -I@"echo./@")


cat hello.txt | sed -e 's/(^)/copy/; s/$/./'"$location"'/;'





str  String  附加  SED  
相关文章