我花了最后90分钟谷歌搜索这个问题所以我希望我不会问一个之前被问过几次的问题.8
我目前正在尝试解析日志文件,并需要一行中的特定值。 文本文件内容:
read: 4163419415 0 0 4163419415 0 4395.007 0
read: 4163419415 0 0 4163419415 0 4395.007 0
read: 4163419415 0 0 4163419415 0 4395.007 1
read: 4163419415 0 0 4163419415 0 4395.007 0
我需要抓住最后一个值(可以是变量)并对其进行一些检查。
COUNTER=1
while [ $COUNTER -lt 26 ]; do
ECREAD=$(awk '/read:/{i++}i=='$COUNTER'{print $8; exit}' ./txt.file)
echo $ECREAD
if [ "$ECREAD" > 0 ]
then
echo "fail"
fi
let COUNTER=COUNTER+1
done
我的问题是if语句总是为真,无论$ ECREAD是什么值。 我试过了
[[ $ECREAD =~ ^-?[0-9]+$ ]] && echo integer
验证变量是否为整数。
我还尝试通过将命令的awk部分导入sed 's/ *$//'
AND sed 's/^ *//'
和tr -d ' '
我尝试将IF语句周围的[]更改为[[]]
AND (( ))
我尝试将>
符号更改为-gt
符号。
答案 0 :(得分:2)
假设我们有inputfile
。我们只想检查前24行。如果这些行中的任何一行以read:
开头并且最后一列大于零,那么我们要打印Fail
。
如果是这种情况,那么:
$ awk '/^read:/ && $NF > 0 {print "Fail";} NR>=24{exit;}' inputfile
Fail
工作原理
/^read:/ && $NF > 0 {print "Fail";}
对于以read:
开头并且其最后一列$NF
大于零的任何行,则会打印Fail
。
NR>=24{exit;}
awk
提供了一个名为NR
的记录(行)计数器。处理完第24行后,程序将退出而无需进一步阅读。
bash
循环替代如果目标是在bash循环内一次使用awk一行,那么尝试:
for ((counter=1; counter<26; counter++))
do
ecread=$(awk -v num=$counter '/read:/ && NR==num {print $8} NR==num{exit;}' ./txt.file)
echo ecread=$ecread
if [ "$ecread" ] && [ "$ecread" -gt 0 ]
then
echo "fail"
fi
done
工作原理
for ((counter=1; counter<26; counter++)); do
这会在计数器上启动bash循环。
ecread=$(awk -v num=$counter '/read:/ && NR==num {print $8} NR==num{exit;}' ./txt.file)
这会将bash变量counter
的值传递给awk作为变量num
。如果行号num
包含read:
,则会打印字段8的值。处理行号num
后,awk退出。
if [ "$ecread" ] && [ "$ecread" -gt 0 ]
这会启动if
- then
语句。如果(a)then
具有非空值,则执行ecread
部分;(b)如果非空值大于零,则执行ECREAD=$(awk '/read :/{print $8; exit}' ./txt.file)
echo ECREAD=$ECREAD
if [ 1 = "$(echo "$ECREAD > 0" | bc)" ]
then
echo "fail"
fi
部分。
尝试:
/read:/
read
与任何内容都不匹配。输入至少在问题中显示,在:
和/read :/
之间有一个空格。因此,测试更改为{i++}o==$COUNTER'
代码ECREAD
的目的不明确,已删除。
示例输入中bc
的值为float:4395.007。 shell只进行整数运算。但是,bc
可以很好地处理浮点数。因此,测试转换为使用[
。
在与shell测试命令>
进行比较时,符号<
和-eq
按字典顺序比较字符串值。对于数字测试,可以使用助记符为-ne
,-lt
,-le
,-gt
,-ge
或ECREAD=4395.007
fail
。
上面提供的示例输入代码的输出是:
read: 4163419415 0 0 4163419415 0 4395.007 0
如果样本输入中存在错位空间,请考虑此替代方案。假设输入如下:
bc
现在,第8个字段不是浮点数而是零。在这种情况下,不需要ECREAD=$(awk '/read:/{print $8; exit}' ./txt.file)
echo ECREAD=$ECREAD
if [ "$ECREAD" -gt 0 ]
then
echo "fail"
fi
,代码可以简化为:
ECREAD=0
以上代码的输出是:
{{1}}
答案 1 :(得分:0)
分配线有点混乱:
ECREAD=$(awk '/read:/{i++}o==$COUNTER'{print $8; exit}' ./txt.file)
有三个单引号,没有反斜杠,这会造成麻烦。你可能需要:
ECREAD=$(awk '/read:/ {i++} o==$COUNTER {print $8; exit}' ./txt.file)
这在语法上是有效的。它并不清楚它是否符合您的期望。如果模式匹配(它不匹配您的样本数据),则变量i
会递增,否则将不使用。测试o == $COUNTER
将未设置的变量o
与$0
进行比较(因为COUNTER
是未设置的变量,因此计算结果为0)。由于条件不正确,因此不执行打印。这可能符合你的意图:
ECREAD=$(awk '/^read :/ { print $8; exit}' ./txt.file)
你的shell&#39; if
&#39;声明是一大堆:
[ if "$ECREAD" > 0 ]
then
echo "fail"
fi
它应该是:
if [ "$ECREAD" -gt 0 ]
then
echo "fail"
fi
或:
if [[ "$ECREAD" -gt 0 ]]
then
echo "fail"
fi
答案 2 :(得分:0)
您可以尝试类似
的内容$ ECREAD=$(awk '$1~/read/{print $7}' input )
$ if [ $ECREAD -gt 0 ]
> then
> echo fail
> else
> echo pass
> fi
pass
答案 3 :(得分:0)
这里的纯bash解决方案就像使用awk
解析文件一样简单。 read
能够在不更改分隔符的情况下阅读space
,tab
或newline
分隔文本(默认:内部字段分隔符$IFS
)。然后,您可以将前七个值读入垃圾变量并丢弃,只留下您感兴趣的ecread
值。
awk
解决方案也很好,但是如果您使用bash工作,它也可以满足您的需求而无需依赖外部流程:
#!/bin/bash
## accept filename as first argument to script (default dat/ecread.dat)
fn="${1:-dat/ecread.dat}"
## validate file is readable
[ -r "$fn" ] || {
printf "error: file not readable '%s'. Usage: %s <filename> (dat/ecread.dat)\n\n" "$fn" "${0//*\//}"
exit 1
}
declare -i counter=1 # declare counter as int, set to 1
## read each line in data-file and discard first 7 values (while counter < 26)
while [ "$counter" -lt 26 ] && read a a a a a a a ecread || [ -n "$ecread" ]; do
printf " ecread: %s" "$ecread"
## test ecread > 0, if so fail, if not OK
[ "$ecread" -gt 0 ] && printf " -- fail\n" || printf " -- OK\n"
counter+=1
done <"$fn"
exit 0
<强>输出:强>
$ bash ecread.sh
ecread: 0 -- OK
ecread: 0 -- OK
ecread: 1 -- fail
ecread: 0 -- OK