在文本文件行中提取部分重复的模式

时间:2018-11-09 17:01:14

标签: regex linux bash command-line

给出以下形式的文本文件:

firstword<number1>,<string1>:<number2>,<string2>:<number3>,<string>:<number4>...
firstword<number1>,<string1>:<number2>,<string2>:<number3>,<string>:<number4>...
firstword<number1>,<string1>:<number2>,<string2>:<number3>,<string>:<number4>...
...

其中每一行可以彼此不同,并且可以具有任意数量的string:number对。 “第一字”始终是相同的。字符串和数字的内容可以更改,例如数字可以是“ 12345”,字符串可以是“ abc”(不带引号)。

此外,同一行可以有多次相同的字符串(多少行是未知的,每行不同),每条都有不同的关联编号。例如:

firstword123,abc:123,cde:234,abc:345,def:456

如果现在只想提取第一个单词和数字(在本例中为firstword123)以及特定字符串的一行中的所有string:number对,那么该怎么做?在上面的示例中,如果为字符串选择值“ abc”,则提取的行应类似于:

firstword123,abc:123,abc:345

我正在寻找一种适用于Bash(以及其他命令)的解决方案。

2 个答案:

答案 0 :(得分:2)

您可以为此使用perl

#!/usr/bin/perl
my $first='firstword123';
my $str='abc';

while (<DATA>) {
    next if not /^$first/;
    print "$first";
    print ",$_" for ($_ =~ /$str:\d+/g);
}

__DATA__
firstword123,abc:123,cde:234,abc:345,def:456

退出:

firstword123,abc:123,abc:345

答案 1 :(得分:1)

不是单线,而是全力以赴的解决方案。如果您需要更快的代码,我们可以用awkperl ...

$: cat keyscan
#! /bin/env bash

key="$1"
while read line
do start=${line//,*/}
   line=${line#$start}
   line=${line#,}
   while [[ -n "$line" ]]
   do case "$line" in
      $key:[0-9]*) lead="${line//,*/}"
                   start="$start,$lead"
                   line="${line#$lead}"
                   line="${line#,}"  ;;
              *,*) line="${line#*,}" ;;
                *) line='' ;;
      esac
   done
   printf "$start\n"
done

$: cat data
firstword123,abc:123,cde:234,abc:345,def:456

$: ./keyscan abc < data
firstword123,abc:123,abc:345

$: ./keyscan def < data
firstword123,def:456

$: ./keyscan cde < data
firstword123,cde:234

它不会很快,因为它在输入的每一行上都有一个处理循环,但是可以在您提供的数据的示例行上工作。