2013-04-26 48 views
2

我有一个日志file.log:grep的同时读取线替代

toto string1 tata string2 tito string3 
tata tati string3 
titi string1 tato string2 tati toto 
..... 
tutu string1 tita string2 tita string3 

我需要从文件中的每一行提取字符串1,字符串和STRING3。 这些行可能包含一个或两个或三个字符串。

我第一次尝试使用,而读线做的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

你想只提取stringX或包含stringX的整行吗? – 2013-04-26 04:23:47

+0

我想提取只是stringX – 2013-04-26 04:32:19

回答

1

有很多方法可以做到这一点。既然你看起来更喜欢外壳,那么你应该看看awk,它基本上就是为了做到这一点而设计的。

Perl也适用于这类任务。一个简单的脚本,用几个正则表达式来匹配您的搜索条件,然后打印。

1

尝试grep -oE "string[0-9]" file.log >> results.csv-o标志只给出匹配的部分作为输出

0

从我可以看到你的字符串模式正在发生变化列:

toto string1 tata string2 tito **string3** 
tata tati string3 
titi string1 tato string2 tati toto 
..... 
tutu string1 tita string2 tita string3 

二号线是第3列,其余的是第2列,所以没有依赖列输出的列号作为ca N为在这里看到:

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 
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 

这可能不是一样快perlawk的解决方案,但应该是在你原来的改善,因为没有额外的过程需要创建;一切都在bash完成。