Bash 如何检查程序的标准输出是否在文件中?
我已经尝试了很多次,尝试了不同的方法,但似乎无法让这个工作。我试图运行一个python脚本并对输出进行grep处理,以查看它是否包含在文件中,如果不是,我想将其附加到所述文件中Bash 如何检查程序的标准输出是否在文件中?,bash,macos,grep,Bash,Macos,Grep,我已经尝试了很多次,尝试了不同的方法,但似乎无法让这个工作。我试图运行一个python脚本并对输出进行grep处理,以查看它是否包含在文件中,如果不是,我想将其附加到所述文件中 $./scan_network.py 22 192.168.1.1 192.168.1.20 | if ! grep -q - ./results.log; then - >> results.log; fi 我知道macOS grep不理解-作为标准输出,然后->>将不起作用,因为它也不会接收标准输出。我
$./scan_network.py 22 192.168.1.1 192.168.1.20 | if ! grep -q - ./results.log; then - >> results.log; fi
我知道macOS grep不理解-作为标准输出,然后->>将不起作用,因为它也不会接收标准输出。我不知道该怎么办
如前所述,主要目标是对照文件检查脚本的输出,如果在文件中找不到IP地址,则需要追加该地址
编辑:
results.log当前是一个空文件。目前,scan_network.py on的输出为192.168.1.6。当我在另一个网络上运行它时,输出将是一个范围内的多个地址,例如10.234.x.y,其中x和y是0到255之间的任意数字。假设脚本返回一行文本,您可以将输出存储在变量中,然后对该字符串进行grep。例如:
logfile="results.log"
# save output to a shell variable
str=$(./scan_network.py 22 192.168.1.1 192.168.1.20)
# don't call grep twice for the same pattern
grep=$(grep -F "$str" "$logfile")
# append if grep results are empty
if [[ -z "$grep" ]]; then
echo "$grep" >> "$logfile"
fi
假设脚本返回一行文本,可以将输出存储在变量中,然后对该字符串进行grep。例如:
logfile="results.log"
# save output to a shell variable
str=$(./scan_network.py 22 192.168.1.1 192.168.1.20)
# don't call grep twice for the same pattern
grep=$(grep -F "$str" "$logfile")
# append if grep results are empty
if [[ -z "$grep" ]]; then
echo "$grep" >> "$logfile"
fi
一个简单的解决方案是将日志文件和程序输出合并到一个新的日志文件中:
sort -u <(./scan_network.py 22 192.168.1.1 192.168.1.20) results.log > newresults.log
sort-u newresults.log
-u
标志会导致从输出中删除重复的行,因此每行只能得到一行
这样做的副作用是对行重新排序(以便按字母顺序排序)。必要时可以维持秩序,但会变得更复杂
使用相当现代的gnu
排序
,您可以使用“版本号”排序,这将合理地保持IP编号的逻辑顺序;您可以使用-V
标志来执行此操作。或者您可以使用sort-u-t对八位字节进行单独排序-k1,1n-k2,2n-k3,3n-k4,4n…
。或者你可以只接受字典排序。不要只使用-n
进行标准数字排序,因为它只检查第一个八位字节,这将与-u
选项产生不幸的交互作用,因为比较相等的两行被认为是重复的。由于numeric sort只考虑数字前缀,因此会有许多错误的重复项 一个简单的解决方案是将日志文件和程序的输出合并到一个新的日志文件中:
sort -u <(./scan_network.py 22 192.168.1.1 192.168.1.20) results.log > newresults.log
sort-u newresults.log
-u
标志会导致从输出中删除重复的行,因此每行只能得到一行
这样做的副作用是对行重新排序(以便按字母顺序排序)。必要时可以维持秩序,但会变得更复杂
使用相当现代的gnu
排序
,您可以使用“版本号”排序,这将合理地保持IP编号的逻辑顺序;您可以使用-V
标志来执行此操作。或者您可以使用sort-u-t对八位字节进行单独排序-k1,1n-k2,2n-k3,3n-k4,4n…
。或者你可以只接受字典排序。不要只使用-n
进行标准数字排序,因为它只检查第一个八位字节,这将与-u
选项产生不幸的交互作用,因为比较相等的两行被认为是重复的。由于numeric sort只考虑数字前缀,因此会有许多错误的重复项 如果您不介意对日志文件进行排序和重写,那么它可以很好地工作。(不幸的是,在macOS上,仅使用-V
进行真正的每组件数字IP地址排序是不可取的)。[1]
这里有一个替代方案,它只在需要时就地附加到现有日志文件中,而不重新排列现有行:
grep -f results.log -xFv <(./scan_network.py 22 192.168.1.1 192.168.1.20) >> results.log
grep-f results.log-xFv>results.log
注意:这假设/scan\u network.py
的输出是基于行的;管道到tr
转换为基于行的输出(如有必要)
将指定文件中的每一行视为单独的搜索项,其中任何项的匹配都被视为整体匹配李>-f
完全匹配行-x
执行文字匹配(不将搜索词解释为正则表达式)-F
仅输出不匹配的行-v
/scan\u network.py…
输出的行在结果.log
中不存在,才会附加到结果.log
但是,请注意,性能可能会受到更大的结果的影响。log
变得更大,因此从长远来看,rici的方法可能更可取,尤其是在日志文件不断增长和/或您仍然希望日志按IP地址排序的情况下
至于你所尝试的:
grep -f results.log -xFv <(./scan_network.py 22 192.168.1.1 192.168.1.20) >> results.log
- GNU和BSD/macOS
都可以选择接受grep
作为stdin的占位符,以接受来自stdin的输入,但请注意,永远不需要此操作数,因为默认情况下-
从stdin读取输入grep
- 相比之下,只有GNU
接受grep
作为-
的选项参数,即包含要应用的搜索词的文件。-f
BSD/macOS需要一个显式文件名、一个进程替换(如上所述),或者在必要的情况下,
来引用stdin/dev/stdin
- 搜索逻辑必须颠倒:如上面的命令所示,现有日志文件内容必须用作搜索词(传递到
),并且-f
输出必须用作输入,以确定哪些行不在日志文件中(/scan\u network.py…
)-v
- 根据上下文,使用
表示stdin或stdout仅仅是一种惯例,只能作为命令使用-