gpt4 book ai didi

linux - unix - awk 意外行为

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:31:11 24 4
gpt4 key购买 nike

我在名为“findError.sh”的 bash 文件中有以下代码:

#!/bin/bash
filename="$1"
formatindicator="\"|\""
echo "$formatindicator"
formatarg="\$1"
echo "$formatarg"
count=`awk -F$formatindicator '{print $formatarg}' $filename | perl -ane '{ if(m/ERROR/) { print } }' | wc -l `
command="awk -F$formatindicator '{print $formatarg}' $filename | perl -ane '{ if(m/ERROR/) { print } }' | wc -l"
echo $command
echo $count

然后我像这样在命令行运行它:sh findError.sh 测试.dat

但它给我的计数与运行回显的命令不同?这怎么可能?

即回显的 $command 是:

awk -F"|" '{print $1}' test.dat | perl -ane '{ if(m/ERROR/) { print } }' | wc -l

但是返回的 $count 是:

3

但是,如果我只是在命令行下面运行这一行(而不是通过脚本)——结果是 0:

awk -F"|" '{print $1}' test.dat | perl -ane '{ if(m/ERROR/) { print } }' | wc -l

示例输入文件(test.dat):

sid|storeNo|latitude|longitude
2|1|-28.03720000
9|2
10
jgn352|1|-28.03ERROR720000
9|2|fdERRORkjhn422-405
0000543210|gfERRORdjk39

注意事项:将 SunOS 与 bash 版本 4.0.17 一起使用

最佳答案

您对格式分隔符周围的引号过于小心。

当你输入时:

awk -F"|" ...

程序 (awk) 将 -F| 视为它的第一个参数; shell 去掉了双引号。

当你有:

formatindicator="\"|\""
echo "$formatindicator"
formatarg="\$1"
echo "$formatarg"
count=`awk -F$formatindicator ...`

您在 $formatindicator 中保留了双引号,因此 awk-F"|" 视为分隔符,并使用双引号引号作为分隔符。

使用:

formatindicator="|"
echo "$formatindicator"
formatarg="\$1"
echo "$formatarg"
count=`awk -F"$formatindicator" ...`

不同之处在于 shell 会去掉 -F"$formatindicator" 中的引号,但当 $formatindicator 本身包含双引号时不会这样做。

(注意:已编辑以保留反引号而不是 $(...) 表示法,这是 (a) 首选和 (b) 用于此答案的第一个版本。 $(...) 符号不被 SunOS /bin/sh 识别,我相信它被用来执行脚本。bashksh 识别 $(...) 符号,但基本的 Bourne shell,/bin/sh,在 Solaris 10 上(SunOS 5.10) 及更早版本(我没有接触过 Solaris 11)无法识别 $(...)。)

我注意到 perlawkgrep 中的任何一个都可以用来自行查找错误行数,所以awk 的三元组通过管道传输到 perl 并通过管道传输到 wc 效率不高。

awk -F"|" '$1 ~ /ERROR/ { count++ } END { print count }' $filename

grep -c ERROR $filename # simple
grep -c '^[^|]*ERROR[^|]*|' $filename # accurate

perl -anF"|" -e '$count++ if $F[0] =~ m/ERROR/; END { print "$count\n"; }' $filename

它是 Perl,所以 TMTOWTDI ;选择你...


边会讨论

在评论中,我们担心脚本的各个部分是如何被解释的。

formatindicator="|"
formatarg="\$1"

count=`awk -F$formatindicator '{print $formatarg}' $filename | perl -ane '{ if(m/ERROR/) { print } }' | wc -l `

让我们将其简化为(使用我的主要答案的一部分):

count=`awk -F"$formatindicator" '{print $formatarg}' $filename`

目的是通过 -F 选项在命令行上指定分隔符(成功发生)。我预计问题是“为什么 $formatarg 在单引号内展开?”。答案是“是吗?”。我想不是。所以,正在发生的事情是 awk 正在查看脚本 {print $formatarg}。由于 formatarg 没有赋值,它相当于 0,所以脚本打印了 $0,也就是整个输入行。如果 Perl 在该行的任何位置匹配 ERROR,Perl 很乐意回显该行,并且 wc 不会关心行中的内容,因此结果大致与预期的一样。唯一会出现差异的情况是 $filename 中的行在第一个竖线分隔字段以外的地方包含 ERROR。这将被脚本计算在不应计算的地方。

关于linux - unix - awk 意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8640811/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com