我有一个日志文件.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。 这些行可以包含一个或两个或三个字符串。
我第一次尝试使用,同时阅读LINE do 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
这可以按预期工作,但它根本没有优化,而且速度很慢。
感谢您的帮助!
答案 0 :(得分:1)
有很多方法可以实现这一目标。既然你似乎更喜欢shell,你应该看一下awk,它基本上就是为了做到这一点。
Perl也适用于此类任务。一个简单的脚本,带有几个正则表达式以匹配您的搜索字词,然后打印。
答案 1 :(得分:1)
try grep -oE "string[0-9]" file.log >> results.csv
-o
标志仅将匹配的部分作为输出
答案 2 :(得分:0)
从我可以看到你的字符串模式正在改变列:
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
答案 3 :(得分:0)
使用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
完成。