每个人。我有
file 1.log:
text1 value11 text
text text
text2 value12 text
file 2.log:
text1 value21 text
text text
text2 value22 text
我想要:
value11;value12
value21;value22
目前,我将grep值放在分开的文件中,然后再粘贴到另一个文件中,但是我认为这不是一个非常好的解决方案,因为我需要多次读取所有文件,因此我尝试使用grep提取所有数据一只猫| grep行,但不是我预期的结果。
我使用:
cat *.log | grep -oP "(?<=text1 ).*?(?= )|(?<=text2 ).*?(?= )" | tr '\n' '; '
或
cat *.log | grep -oP "(?<=text1 ).*?(?= )|(?<=text2 ).*?(?= )" | xargs
但在每种情况下我都会得到:
value11;value12;value21;value22
value11 value12 value21 value22
非常感谢您。
答案 0 :(得分:0)
尝试:
$ awk -v RS='[[:space:]]+' '$0=="text1" || $0=="text2"{getline; printf "%s%s",sep,$0; sep=";"} ENDFILE{if(sep)print""; sep=""}' *.log
value11;value12
value21;value22
对于那些喜欢将命令分布在多行上的人:
awk -v RS='[[:space:]]+' '
$0=="text1" || $0=="text2" {
getline
printf "%s%s",sep,$0
sep=";"
}
ENDFILE {
if(sep)print""
sep=""
}' *.log
-v RS='[[:space:]]+'
这告诉awk将空白序列(换行符,空格,制表符等)视为记录分隔符。
$0=="text1" || $0=="text2"{getline; printf "%s%s",sep,$0; sep=";"}
这告诉awk查找与text1 or
text2`匹配的文件记录。对于那些记录和那些记录,仅执行大括号中的命令。这些命令是:
getline
告诉awk读取下一条记录。
printf "%s%s",sep,$0
告诉awk打印变量sep
,后跟记录中的单词。
在打印第一个匹配项之后,将执行命令sep=";"
,该命令告诉awk将sep
的值设置为分号。
启动每个文件时,sep
为空。这意味着将打印任何文件中的第一个匹配项,并且前面没有分隔符。同一文件中的所有后续匹配项都将带有;
来分隔它们。
ENDFILE{if(sep)print""; sep=""}
到达每个文件的末尾后,如果sep
不为空,则打印换行符,然后将sep
设置为空字符串。
在对问题的另一种解释(提示:David C. Rankin)中,我们想在第一个单词以数字结尾的任何行上打印第二个单词。在这种情况下,请尝试:
$ awk '$1~/[0-9]$/{printf "%s%s",sep,$2; sep=";"} ENDFILE{if(sep)print""; sep=""}' *.log
value11;value12
value21;value22
在上面,$1~/[0-9]$/
选择第一个单词以数字结尾的行,printf "%s%s",sep,$2
在该行上打印第二个字段。
原始命令是:
$ cat *.log | grep -oP "(?<=text1 ).*?(?= )|(?<=text2 ).*?(?= )" | tr '\n' '; '
value11;value12;value21;value22;
请注意,在使用大多数UNIX命令时,几乎不需要cat
。在这种情况下,例如,grep
接受文件列表。因此,我们无需额外的cat
流程就可以轻松完成操作,并获得相同的输出:
$ grep -hoP "(?<=text1 ).*?(?= )|(?<=text2 ).*?(?= )" *.log | tr '\n' '; '
value11;value12;value21;value22;
答案 1 :(得分:0)
我同意@John1024的看法,您如何解决此问题实际上取决于您要寻找的实际文本。例如,如果您的关注点从text{1,2,...}
开始,然后在第二个字段中想要的内容可以是任何内容,那么他的方法是最佳的。但是,如果第一个字段中的值各不相同,而您真正感兴趣的是第二个字段中有valueXX
的记录,那么寻找第二个字段的方法可能就是您想要的。 / p>
以第二个字段为例,如果您感兴趣的文本的格式为valueXX
(其中XX
是字段末尾的两位或多个数字),则只能处理那些与您的第二个字段匹配的记录,然后使用简单的条件测试,来类似于FNR == 1
是否控制';'
分隔符输出和ENDFILE
是否控制新行:
awk '$2 ~ /^value[0-9][0-9][0-9]*$/ {
printf "%s%s", (FNR == 1) ? "" : ";", $2
}
ENDFILE {
print ""
}' file1.log file2.log
使用/输出示例
$ awk '$2 ~ /^value[0-9][0-9][0-9]*$/ {
printf "%s%s", (FNR == 1) ? "" : ";", $2
}
ENDFILE {
print ""
}' file1.log file2.log
value11;value12
value21;value22
仔细研究一下并考虑您的实际输入文件,然后这两种方法中的任何一种都可以使您到达那里。
答案 2 :(得分:0)
如果我对您的理解正确,则需要values
,但要搜索text[12]
,即。在匹配搜索字词之后而不是匹配搜索字词后得到字词:
$ awk -v s="^text[12]$" ' # set the search regex *
FNR==1 { # in the beginning of each file
b=b (b==""?"":"\n") # terminate current buffer with a newline
}
{
for(i=1;i<NF;i++) # iterate all but last word
if($i~s) # if current word matches search pattern
b=b (b~/^$|\n$/?"":";") $(i+1) # add following word to buffer
}
END { # after searching all files
print b # output buffer
}' *.log
输出:
value11;value12
value21;value22
{*
regex也可以是^(text1|text2)$
。