Bash 与grep while prinf相比,使用rege从日志文件中提取值更简单、更优雅
我有几个日志文件看起来像:Bash 与grep while prinf相比,使用rege从日志文件中提取值更简单、更优雅,bash,grep,printf,Bash,Grep,Printf,我有几个日志文件看起来像: #LOGa# 180.149.126.169 ## 85 with value 350.00000000000000000000 due brand: 350.00000000000000000000 country: 0 {2020-11-26_11-01-00} #DETAILS_hits# 180.149.126.169 ## hits=([brand/17]="1" [brand/18]="1" [no_brand]=&
#LOGa# 180.149.126.169 ## 85 with value 350.00000000000000000000 due brand: 350.00000000000000000000 country: 0 {2020-11-26_11-01-00}
#DETAILS_hits# 180.149.126.169 ## hits=([brand/17]="1" [brand/18]="1" [no_brand]="1" ) {2020-11-26_11-01-00}
#LOG_brand# 180.149.126.169 ## BRANDS=([anyBrand]="1" ) {2020-11-26_11-01-00}
#LOG_country# 180.149.126.169 ## COUNTRY=([anyCountry/17]="1" [anyContinent/18]="1" ) {2020-11-26_11-01-00}
我想提取一些特殊对数线的圆顶值
我当然可以和你一起去
grep -HiRE "(#LOGa#)(.+)(## )(.+)" --include \myFile.log | while read _ ip _ rank _ value _ _ valueBrand _ _ valueCountry _ ; do printf "%.0f %.0f\n" $valueBrand $valueCountry; done
但这不是一种更优雅的方式,
类似
cleanME myFile.log "(#LOGa#)($ip)(## )($rank)(with value)($value)(due brand:)($valueBrand)(country:)($valueCountry)(.*)" "$valueBrand.0f $valueCountry.0f"
当然,我可以构建这样的函数,但我不记得它比grep+while+printf更好。如果您选择
Perl
,请尝试:
perl -ne '/^#LOGa#\s+([\d.]+)\s+##\s+([\d.]+)\s+with value\s+([\d.]+)\s+due brand:\s+([\d.]+)\s+country:\s+([\d.]+)/ && printf "%.0f %.0f\n", $4, $5' myFile.log
所提供输入的输出:
350 0
- 选项
告诉-n
以Perl
的形式逐行处理输入文件sed
- 选项
启用一行程序-e
- 语法
仅当行 将正则表达式匹配为/regex/&&printf…
grep
- 正则表达式中的参数创建捕获组和匹配的子字符串
可以使用
,$1
。。。按顺序$2
我不确定这是否更好,但是考虑一下:
find . -type f -name myFile.log -print | xargs sed -En 's/^#LOGa# .+ ## .+ with value [0-9.-]+ due brand: ([0-9.-]+) country: ([0-9]+).*$/\1 \2/1;Tx;p;:x'
说明:
find
——在当前目录(
)中递归查找名为myFile.log(-name myFile.log
)和-print
的所有文件(-type f
)。(sed
没有像grep
这样的-R
选项)将此管道传输到xargs
,对于每个管道,xargs将调用流编辑器sed
,使用扩展的regexp语法(-E
)并且不自动打印行(-n
)。替换(s/
)给定的regexp,使用分组运算符捕获valueBrand和valueCountry,并替换第一次出现(/1
)时括号(\1\2
)中捕获的整行值。然后,如果此替换未发生,则跳转到标签x(;Tx
);否则p
打印该行。然后是标签x(;:x
)和end(仅退出)
我不确定您是否有意截断输出中的小数位;要做到这一点,您必须通过
bash
printf
语句(在读取b时;do printf“%.0f%.0f”ab;done
)或其他程序,或者以另一种方式执行。或者,如果您真的想将(即不是四舍五入)截断到小数点后零位,您可以使用品牌:([0-9-]+)\.[0-9]*
而不是品牌:([0-9-]+)
。这只是将小数点和尾数从字符串中排除,然后将其删除。为了更好地理解问题,请在问题中添加示例预期输出。为什么不只添加awk
是不是一种更优雅的方式
你的问题到底是什么?“优雅”可能是基于观点的。我们不知道你“不记得”什么。