为什么这样做
for myfile in `find . -name "R*VER" -mtime +1`
do
SHELLVAR=`grep ^err $myfile || echo "No error"`
ECHO $SHELLVAR
done
和输出
No error
err ->BIST Login Fail 3922 err
No error
err ->IR Remote Key 1 3310 err
但这不是
for myfile in `find . -name "R*VER" -mtime +1`
do
SHELLVAR=`grep ^err $myfile || echo "No error"`
awk -v awkvar=${SHELLVAR} '{print awkvar}'
done
和输出
awk: cmd. line:1: fatal: cannot open file `{print awkvar}' for reading (No such file or directory)
我错过了什么?
答案 0 :(得分:5)
$SHELLVAR
是否包含空格?如果是这样,你的awk脚本会被误解,并且{print awkvar}
被假定为文件名而不是实际的AWK程序。
您还遇到一个问题, for 循环和 awk 程序都在啜饮STDIN。事实上,你的for循环只会被执行一次,因为AWK将在所有STDIN中读取,直到它完成。最后,你会一遍又一遍地获得同一行,然后你的程序将停止运行,因为awk
等待更多STDIN。
我想你想做这样的事......
find . -name "R*VER" -mtime +1 | while read myfile
do
echo "$SHELLVAR" | awk '{print $0}'
done
这样,你的echo命令会输入你的awk,这会阻止awk从find语句中读取。
顺便说一句,你最好这样做:
find . -name "R*VER" -mtime +1 | while read myfile
do
...
done
而不是:
for myfile in `find . -name "R*VER" -mtime +1`
do
...
done
这有几个原因:
命令行缓冲区可能会溢出,您将丢失文件名,但您永远不会看到错误。
第二个示例中的find命令必须先完成,然后才能开始执行for循环。在第一个示例中,查找提供到while循环。
现在我看到了just-my-correct-opinion的回答,我意识到你做错了什么:你忘记了awk
命令中的文件名:
find . -name "R*VER" -mtime +1 | while read myfile
do
SHELLVAR=`grep ^err $myfile || echo "No error"`
awk -v awkvar=${SHELLVAR} '{print awkvar}' $myfile
done
现在,问题是你究竟在用awk
做什么。除了$SHELVAR
的值之外,您不会为文件中的每一行打印任何内容。这可能不是你想要做的。事实上,为什么不简单地这样做:
find . -name "R*VER" -mtime +1 | while read myfile
do
SHELLVAR=$(grep -q "^err" $myfile")
if [ "x$SHELLVAR" != "x" ]
then
echo "$SHELLVAR"
fi
done
这样,您打印$SHELLVAR
,但仅当$SHELLVAR
为空。
或者,您可以使用awk仅打印出与正则表达式匹配的行:
find . -name "R*VER" -mtime +1 | while read myfile
do
awk '/^err/ {print $0}' $myfile
done
答案 1 :(得分:5)
你想做的事情是可能的,但......有点古怪。这是您的另一种选择:
for f in $(find . -name "R*VER" -mtime +1)
do
echo "$f"
awk 'BEGIN{ec=0} /^err/{ec+=1;print} END{if(ec==0){print "No error"}}' "$f"
done
这样您就不必担心grep
,不必担心shell变量,并且可以用一种语言将逻辑保存在一个地方。
请注意,此代码仅部分测试,因为我没有您的数据文件,但测试我做得很好。
如果你愿意,你甚至可以更进一步,在awk
中写下整件事。毕竟,它是一种完整的通用编程语言(IMO,比bash
更清晰的语法)。这样您就可以完全避免使用find
,grep
和bash
。但是,我不会写那个剧本。您必须选择awk
手册页并自行阅读文件I / O.
答案 2 :(得分:4)
您需要引用$SHELLVAR
,以防止shell分裂它。
awk -v awkvar="${SHELLVAR}" '{print awkvar}'
答案 3 :(得分:1)
您已经有了替代解决方案。无论如何,我只想回答你的问题,即你缺少的东西:
awk -v awkvar=${SHELLVAR} '{print awkvar}'
这里awk正在寻求从STDIN
读取输入。这就是问题。 Awk试图从STDIN
读取输入,除非您指定输入文件。对输入中的每个RECORD
执行awk的给定命令(默认情况下,记录是一行)。请参阅man awk
以了解有关awk的更多信息。
但是如果你想让它在没有任何输入的情况下继续进行,那么这是一个黑客攻击:
awk -v awkvar=${SHELLVAR} 'BEGIN{print awkvar}'
一旦调用awk
,就会执行BEGIN块。如果awk
找不到除BEGIN
之外的任何其他块,则会执行这些BEGIN
块并退出。
我希望你能解决错误背后的问题,并为此提供快速解决方案。