具有多个分隔符的切片字符串

时间:2016-11-28 05:48:51

标签: bash unix slice

我有许多目标行的日志文件,我希望'grep',例如:

EGPA019_90pc.recode.2.log:Cross-Entropy (masked data):   0.556984

我希望将“2”和“0.556984”用标签分隔成文件

所以,如果我输入:

grep "Cross-Entropy (masked data):" *.log | cut -d '.' -f 3 >> targetFile.txt

我得到“2”,并且:

grep "Cross-Entropy (masked data):" *.log | cut -d ' ' -f 4 >> targetFile.txt

我得到了“0.556984”。但是我怎么能在一行代码中写这个以获得“2”然后在我的目标文件中的同一行上的选项卡然后“0.556984”?

非常感谢

克里夫

3 个答案:

答案 0 :(得分:2)

您可以使用grep和一些bash内置的regEx功能。

grep -h "Cross-Entropy (masked data):" *.log | while IFS= read -r string; do
       [[ "$string" =~ .recode.([[:digit:]]+).*:\ (.*)$ ]] 
       printf "%s\t%s\n" "${BASH_REMATCH[1]}"  "${BASH_REMATCH[2]//[[:blank:]]}";
done

我的输入文件

$ cat *.log
EGPA019_90pc.recode.2.log:Cross-Entropy (masked data):   0.556984
EGPA019_90pc.recode.9.log:Cross-Entropy (masked data):   0.996984
EGPA019_90pc.recode.7.log:Cross-Entropy (masked data):   0.756984

$ grep -h "Cross-Entropy (masked data):" *.log | while IFS= read -r string; do
       [[ "$string" =~ .recode.([[:digit:]]+).*:\ (.*)$ ]] 
       printf "%s\t%s\n" "${BASH_REMATCH[1]}"  "${BASH_REMATCH[2]//[[:blank:]]}"; done
2       0.556984
9       0.996984
7       0.756984

说明: -

  1. 使用内置的bash regEx功能来捕获所需的字符串,而不是使用其他本机工具。
  2. grep的输出通过管道传输以应用regEx [ "$string" =~ recode.([[:digit:]]+).*:\ (.*)$ ]],它会捕获您所需的条目,数字和十进制数字。
  3. 使用printf打印这些变量。第二次捕获,即十进制数字在开头有空格字符,将其删除"${BASH_REMATCH[2]//[[:blank:]]}"
  4. 您也可以将它包装在shell脚本中,如下所示: -

    #!/bin/bash
    
    while IFS= read -r string; do
        [[ "$string" =~ .recode.([[:digit:]]+).*:\ (.*)$ ]]
        printf "%s\t%s\n" "${BASH_REMATCH[1]}"  "${BASH_REMATCH[2]//[[:blank:]]}"
    done < <(grep -h "Cross-Entropy (masked data):" *.log)
    

    或者)grep使用PCRE标记-P选项,使用xargs过滤输出。

    grep -Pho '\.recode\.\K\d+|: \K.*' *.log | xargs -n2 -d'\n'
    2   0.556984
    9   0.996984
    7   0.756984
    

    (或)使用更简单的perl regEx语法。

    perl -lne 'print "$1 $2" if /\.recode\.(\d+).*:\s+(.*)/' *.log
    2 0.556984
    9 0.996984
    7 0.756984
    

答案 1 :(得分:0)

我认为我是使用awk执行此操作而不是解析grep的输出。

我没有对您的数据集进行测试,但在我看来,以下情况应该有效。

awk '/^Cross-Entropy \(masked data\):/ {split(FILENAME,a,".");printf("%s\t%s\n", a[3], $NF}' *.log

它有点像单线。作为独立脚本,它可能如下所示:

#!/usr/bin/awk -f

/^Cross-Entropy \(masked data\):/ {
  split(FILENAME,a,".")
  printf("%s\t%s\n", a[3], $NF
}

将其保存在一个文件中,使其可执行,并为自己创建一个全新的shell命令。

请注意,这可以通过使用字段拆分来实现,而不是使用正则表达式。

答案 2 :(得分:0)

您可以使用sed删除不需要的内容:

grep "Cross-Entropy (masked data):" *.log | sed 's/.*recode.//;s/\..*: //' 

可以合并grepsed

sed -n '/Cross-Entropy (masked data):/ {s/.*recode.//;s/\..*: //;p}' *.log