用于包装嘈杂的python脚本并使用sed删除特定行的shell命令问题[重复]

Posted

技术标签:

【中文标题】用于包装嘈杂的python脚本并使用sed删除特定行的shell命令问题[重复]【英文标题】:Issue with shell command used to wrap noisy python script and remove specific lines with sed [duplicate] 【发布时间】:2016-01-27 01:27:55 【问题描述】:

我正在使用一个 python 脚本,它基于完全正常的错误测试证书输出许多警告/错误(进入标准错误)。基于几个 SO 帖子,我能够找到一种方法来运行脚本并忽略 select stdout、stderr 行,但它很麻烦:

runThing 3>&1 1>&2 2>&3 3>&- | grep -r 's/Insecure/'
 OR 
runThing 3>&1 1>&2 2>&3 3>&- | sed 's/Insecure/g'

两者都过滤掉很多行,例如:

 /Users/xxx/.blah/lib/python2.7/site-   packages/requests/packages/urllib3/connectionpool.py:791: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html  InsecureRequestWarning)

但是 sed 有这个错误: sed: 1: "s/Insecure/g": 正则表达式中未终止的替换

在一个经常使用的行的末尾添加了很多内容(真正的 runThing 有命令和参数),所以我试图制作一个类似的命令:

runThingClean()  command runThing "$@" > /dev/null 3>&1 1>&2 2>&3 3>&- | sed 's/Insecure/g' & 

当我运行它时,它现在无法过滤(并显示错误是使用了 sed):

 sed: 1: "s/Insecure/g": unterminated substitute in regular expression

有人可以帮我解决这个命令吗?

提前谢谢..

【问题讨论】:

顺便说一句,您是否考虑过-W once,最多打印一次每个警告?如果问题出在噪音水平上,那会让您感到相当满意。 【参考方案1】:

根本不要这样做:只要告诉 Python 一开始就不要打印警告,然后你就不需要过滤掉它们了。

python -W ignore yourprogram ...

或者,考虑修改调用相关组件的代码以抑制调用站点的警告,如given in the Python documentation:

import warnings
with warnings.catch_warnings():
    warnings.simplefilter('ignore')
    urllib3.doTheThingThatCausedTheWarning(...)

最后,如果你真的想在进程外作为过滤器,只需使用grep -v Insecuresed 的锤子比这项工作所需的要大。

sh -c 'printf "%s\n" "stderr: keep" "stderr: Insecure" >&2; echo "stdout"' \
  3>&1 1>&2 2>&3 3>&- | grep -v Insecure 3>&1 1>&2 2>&3 3>&-

所有这些重定向所做的是交换 stdout 和 stderr 两次——一次在 grep 之前,一次在恢复它们之后。让我们看看它是如何工作的:

FD 1(原始标准输出)被复制到 FD 3(作为备份) FD 2(原始 stderr)被复制到 FD 1(因此可以过滤) FD 3(原始 stdout 的备份)被复制到 FD 2(现在存储在 stderr 中) FD 3 已关闭,因为交换完成后不再需要它。

【讨论】:

感谢您的提示。不过,我希望不要抑制所有警告,并且无法修改代码。出于某种原因,这个: clean() command dirty "$@" > /dev/null 3>&1 1>&2 2>&3 3>&- | grep -v s/Insecure/ & 不会过滤其中包含 Insecure 的行。我想知道管道是否在工作? 您将 FD 1 重定向到 /dev/null,然后将 /dev/null 上的句柄复制到 FD 3?逻辑看起来不太对。 @chrismead, ...我在这里扩展了答案以提供一个经过测试的工作示例(在 grep 之后还将 stderr 和 stdout 移回其原始 FD)。 再次感谢@Charles Duffy。我现在正在尝试这个: clean() 命令嘈杂 "$@" 3>&1 1>&2 2>&3 3>&- | grep -v Insecure 3>&1 1>&2 2>&3 3>&- & 它仍然不起作用,但我想知道“嘈杂”是否运行另一个程序作为其操作的一部分。在这种情况下,可能 stdout、stdin、stderr 会有所不同? @chrismead,不幸的是,取决于细节。如果您有直接将输出写入 TTY 的内容,您将无法在不使用 script 之类的东西将其返回到 stdout/stderr 的情况下对其进行过滤。【参考方案2】:

该错误表示您没有正确关闭sed 中的s。对于s,它应该是s/regex/substitution/g

如果您尝试删除 Insecure 或替换:

sed 's/Insecure/YOUR_SUBSTITUTION/g'

如果您尝试只显示带有Insecure 的行:

sed -n '/Insecure/p'

【讨论】:

感谢您的帮助。如果我这样做: clean() command dirty "$@" > /dev/null 3>&1 1>&2 2>&3 3>&- | sed 's/Insecure//g' & 我没有收到任何错误,但也没有删除包含 Insecure 的行。

以上是关于用于包装嘈杂的python脚本并使用sed删除特定行的shell命令问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在文件中搜索字符串并通过 Shell 脚本将其从该文件中删除 [重复]

用于传递文件名并运行的 shell 脚本 [重复]

shell脚本中执行mysql sql脚本文件并传递参数

使用 sed 从文本文件中删除特定的行号?

如何在 sed 脚本中使用 sed 删除括号内的字符串?

使用 sed 删除特定模式之前的两行