【问题标题】:Awk script vs shell command - different results?awk 脚本与 shell 命令 - 不同的结果?
【发布时间】:2023-05-08 22:05:01
【问题描述】:

第一件事 - 抱歉标题有点误导,还不知道如何描述。

基本上,我有一个关键字列表,我想获取谷歌每次查询返回的文档数量。我创建了以下 awk 脚本:

{
    x = ""
    for(i=1;i<=NF;i++) {
        if(i==NF) {
            x = x $i
        } else {
            x = x $i "+"
        }
    }
    tab = "777" # id of an existing chrome tab as reported by 'chrome-cli list tabs'
    system("chrome-cli open http://www.google.com/search?hl=en\\&q="x" -t " tab)
    system("chrome-cli source -t " tab " | grep '<div id=\"resultStats\">About .* results<nobr>' | head -1 | sed -e 's/.*>About \(.*\) results<nobr>.*/\1/' | awk '{print $1\"\t"x"\"}' >> freq.log " );
    system("cat freq.log" );
    system("sleep 0.5");
}

这里发生的情况是,我首先用 + 号替换所有空格,执行 chrome-cli 命令以在该特定窗口打开 chrome,下载源代码并解析“关于”和“结果”字符串之间的数字并附加结果到freq.log。但是,这会将以下字符串输出到文件中(用于术语警报):

"})();</script><div alarm" 

当我从 iOS 终端执行相同的命令时,我得到一个正确的数字(返回 127.000.000):

chrome-cli source -t 777 | grep  '<div id="resultStats">About .* results<nobr>' | head -1 | sed -e 's/.*>About \(.*\) results<nobr>.*/\1/'

所以我的问题基本上是,虽然一切都在终端上正常工作,但只要我将代码移动到 awk 并使用对系统的调用执行它,就会出现问题并且正则表达式不再起作用。

【问题讨论】:

  • 可能会得到不同的数据。
  • 在 awk 中使用 system() 是危险的——安全漏洞级别的危险。而在带有变量 $var 的 shell 中,您可以运行 some-command "$var"绝对确定该变量可能具有的任何可能值——即使是恶意制作的——它也不能被解析为除了一个参数之外,当你使用字符串连接来形成一个 shell 命令时,它本质上能够逃避它的引用并成为语法。将 tab 文字值 $(rm -rf ~)'$(rm -rf ~)' 视为一个有启发性的示例 - 无论周围的引用类型如何,一种或另一种形式都会触发。
  • 查看关于shell=True 的警告in the Python subprocess documentation -- 您在此处的曝光实际上是相同的。

标签: macos shell awk


【解决方案1】:

您已经在 system 命令中正确地转义了 ",但看起来您还没有在 sed 命令中转义 \。当它到达 sed 时,\( 被视为普通的(
尝试将您的 system 语句更改为 print,您就会明白我的意思了。

在最坏的情况下,您可以将一系列 system 命令捆绑到一个 shell 脚本中,然后让 awk 调用它……但在这种情况下,您不妨完全使用 shell 脚本而不是 awk。

【讨论】: