我有一个日志file.log:
toto string1 tata string2 tito string3 tata tati string3 titi string1 tato string2 tati toto ..... tutu string1 tita string2 tita string3
我需要从文件的每一行中提取string1,string2和string3。 行可以包含一个或两个或三个string。
我第一次尝试使用,而阅读LINE做grep:
while read line; do z_string1=`echo $line | egrep 'string1' | cut -f2 xxx | cut -f1 xxxx` z_string2=`echo $line | egrep 'string2' | cut -f2 xxx | cut -f1 xxxx` z_string3=`echo $line | egrep 'string3' | cut -f2 xxx | cut -f1 xxxx` echo "$z_string1,$z_string2,$z_string3" >> results.csv done < file.log
这可以按预期的方式工作,但是并没有完全优化,而且速度很慢。
感谢您的帮助!
有很多方法来实现这一点。 因为你似乎更喜欢shell,所以你应该看看awk ,这基本上是为了做到这一点。
Perl也专门用于这类任务。 一个简单的脚本,有几个正则表达式来匹配您的搜索条件,然后是一个打印。
尝试grep -oE "string[0-9]" file.log >> results.csv
-o
标志只给出匹配的部分作为输出
从我可以看到你的字符串模式正在改变列:
toto string1 tata string2 tito **string3** tata tati string3 titi string1 tato string2 tati toto ..... tutu string1 tita string2 tita string3
第二行是第三列,其余的是第二列,所以没有依靠列号输出的点可以在这里看到:
awk -v pattern="string" '{cols=NF; if ( (cols == 6 ) && ($2 ~ pattern)) { print $2 " " $4 " " $6 } }' test.txt string1 string2 string3 string1 string2 toto string1 string2 string3
所以..
你可以使用这个或这部分的解决方案
awk -v p1="string1" -v p2="string2" -v p3="string3" 'BEGIN { c1=0; c2=0; c3=0; } {if (( $0 ~ p1) || ( $0 ~ p2) || ($0 ~ p3 )) { for (i=1;i<=NF;i++) { if ( $i ~ p1) { print $i; c1++; } else if ( $i ~ p2) { print $i; c2++; } else if ( $i ~ p3) { print $i; c3++; } } } } END{ print p1"_count:" c1 " "p2"_count:" c2" "p3"_count:"c3} ' test.txt
这产生:
string1 string2 string3 string3 string1 string2 string1 string2 string3 string1_count:3 string2_count:3 string3_count:3
使用bash
正则表达式匹配捕获字符串(如果存在),然后打印它们。 我从你的例子中假设你只是想打印一个空字符串,如果没有找到匹配,所以我保留这种行为。
while read line; do [[ $line =~ (string1) ]]; printf "%s," "$BASH_REMATCH" [[ $line =~ (string2) ]]; printf "%s," "$BASH_REMATCH" [[ $line =~ (string3) ]]; printf "%s\n" "$BASH_REMATCH" done
这可能不像perl
或awk
解决方案那样快,但应该是对原始的改进,因为不需要创建额外的进程; 一切都在bash
完成。