【问题标题】:Perl / grep / awk -- splitting multiple results, if statement checking for second stringPerl / grep / awk -- 拆分多个结果,if 语句检查第二个字符串
【发布时间】:2011-06-04 04:26:55
【问题描述】:

我正在尝试为字符串的前 2 个匹配项(最多只有 2 个匹配项)包括一些上下文(grep -B 1 -A 5),将每组 7 行分成两部分分隔变量并根据每个集合是否包含不同的字符串编写 if 语句。

在某些情况下,文件可能只包含一个匹配项。

我知道如何对两个匹配项进行 grep,但不知道如何将它们拆分为单独的变量。我还可以编写一个 if 语句来检查变量是否为空(表示缺少第二个匹配项)。我不确定如何检查每个变量以查看它是否包含第二个字符串。任何帮助都会有所帮助。谢谢!

例子:

grep -B1 -A5 "解决方案:"file.txt

Color LCD:
  Resolution: 1440 x 900
  Pixel Depth: 32-Bit Color (ARGB8888)
  Main Display: Yes
  Mirror: Off
  Online: Yes
  Built-In: Yes
LED Cinema Display:
  Resolution: 1920 x 1200
  Depth: 32-Bit Color
  Core Image: Hardware Accelerated
  Mirror: Off
  Online: Yes
  Quartz Extreme: Supported

基于每个匹配集是否包含“主显示”的期望结果:

$mainDisplay = 彩色 LCD

$secondDisplay = LED Cinema Display(或 null 表示没有第二个匹配)

【问题讨论】:

  • 提供一个小的示例输入和期望的结果可能有助于说明您的目标。
  • 如果匹配的距离太近,就不会有两组7行;在这种情况下你想要什么?
  • 我提供了示例输入。
  • 根据我的经验,在我梳理的 7 行数据中,我捕捉到了我需要的信息而没有重叠。谢谢:)

标签: perl awk grep


【解决方案1】:

你的文件是有效的 YAML,所以如果你已经安装了 YAML perl 模块,这里有一个 oneliner:

eval $(perl -MYAML -0777 -e '$r=Load(<>);map { exists($r->{$_}->{"Main Display"}) ? print "main=\"$_\";\n" : print "second=\"$_\";\n" } keys %$r' < filename.txt)
echo =$main= =$second=

所以,在 eval 之后,这里是 shell 变量 mainsecond

或者,对于您的 OS X,使用 system_profiler 命令:

eval $(
    system_profiler SPDisplaysDataType |\
    grep -B1 -A5 'Resolution:' |\
    perl -MYAML -0777 -e '$r=Load(<>);map { printf "%s=\"%s\"\n", exists($r->{$_}->{"Main Display"}) ? "main" : "second", $_ } keys %$r'
)
echo =$main=$second=

【讨论】:

    【解决方案2】:
    my($first, $second) = split /--\n/, qx/grep -B1 -A5 foo data.text/;
    

    【讨论】:

      【解决方案3】:

      awk:

      awk -F : '
          /^[^[:space:]]/ {current = $1; devices[$1]++}
          $1 ~ /Main Display/ {main = current}
          END {
              for (d in devices)
                  if (d == main)
                      print "mainDisplay=\"" d "\""
                  else
                      print "secondDisplay=\"" d "\""
          }
      '
      

      输出

      mainDisplay="Color LCD"
      secondDisplay="LED Cinema Display"
      

      您可以在 shell 中捕获并eval

      【讨论】:

        【解决方案4】:

        这是一个 perl 解决方案。像这样使用它:script.pl Resolution:。默认搜索是“分辨率:”。

        值存储在%values,例如:

        $values{Color LCD}{Resolution} == "1440 x 900";

        use strict;
        use warnings;
        
        my $grep = shift || "Resolution:";
        
        my %values;
        my $pre;
        while (my $line = <DATA>) {
            chomp $line;
            if ($line =~ /$grep/) {
                my @data;
                push @data, scalar <DATA> for (0 .. 4);
                chomp @data;
                for my $pair ($line, @data) {
                    if ($pair =~ /^([^:]+): (.*)$/) {
                        $values{$pre}{$1} = $2;
                    } else { die "Unexpected data: $pair" }
                }
            } else {
                $pre = $line;
            }
        }
        
        use Data::Dumper;
        
        print Dumper \%values;
        
        __DATA__
        Color LCD:
          Resolution: 1440 x 900
          Pixel Depth: 32-Bit Color (ARGB8888)
          Main Display: Yes
          Mirror: Off
          Online: Yes
          Built-In: Yes
        LED Cinema Display:
          Resolution: 1920 x 1200
          Depth: 32-Bit Color
          Core Image: Hardware Accelerated
          Mirror: Off
          Online: Yes
          Quartz Extreme: Supported
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-29
          • 1970-01-01
          • 1970-01-01
          • 2017-03-09
          • 2015-10-27
          • 1970-01-01
          • 2015-12-02
          • 1970-01-01
          相关资源
          最近更新 更多