从文件中仅提取特定的多个模式

从文件中仅提取特定的多个模式

我有以下文件:

 $less dummyKeyAndValue.txt
   apiKey=key1;some_other_data;term=abc
   apiKey=key2;some_other_data;some_other_data;term=def
   term=pqr;some_other_data;apiKey=key1
   apiKey=key3;some_other_data;term=def

我想要的输出如下:

 $less dummyNewFile.txt
   apiKey=key1 term=abc
   apiKey=key2 term=def
   apiKey=key1 term=pqr
   apiKey=key3 term=def

主要是,我想从 dummyKeyAndValue.txt 文件中提取“apiKey”和“term”,它们都可以在文件中以不同的顺序出现。我尝试了以下命令:

   $cat dummyKeyAndValue.txt | tee >(egrep -o 'apiKey=[a-zA-Z0-9]+')  |   
   egrep -o 'term=[a-zA-Z]+' | less

我得到的输出为:

     term=abc
     term=def
     term=pqr
     term=def

有人可以帮助我使用命令来获得所需的输出吗?

答案1

这个基于 awk 的解决方案可以提供帮助,因为它更易于阅读/维护。 awk 通常是从文本文件中解析类似列的值的首选工具。

/tmp$ cat a.awk
{
   keypart=substr($0, index($0, "apiKey=")+7)
   keyvalue=substr(keypart, 1, index(keypart, ";")-1)

   termpart=substr($0, index($0, "term=")+5)
   termvalue=substr(termpart, 1, index(termpart, ";")-1)

# If the attribute is last on the input line there will be no ; to mark the end so use the whole part
   if(keyvalue=="") {keyvalue=keypart}
   if(termvalue=="") {termvalue=termpart}
   printf ("  apikey=%s term=%s\n", keyvalue, termvalue)
}

Awk 脚本(上面名为 a.awk,但可以使用任何有意义的文件名)可以像这样使用:

awk -f a.awk inputfile

正如您所看到的,我处理了在行末尾结束的输入字段的情况,特别是每个字段都有一个 if 语句。我将按如下方式增强此脚本以自动处理这些情况:

/tmp$ cat a.awk  
{
   LINE=$0 ";"

   keypart=substr(LINE, index(LINE, "apiKey=")+7)
   keyvalue=substr(keypart, 1, index(keypart, ";")-1)

   termpart=substr(LINE, index(LINE, "term=")+5)
   termvalue=substr(termpart, 1, index(termpart, ";")-1)

   printf ("  apikey=%s term=%s\n", keyvalue, termvalue)
}

当您添加更多案例时,这样做的好处就会变得更加明显!

答案2

作为替代方案,一种非常有效但稍微复杂的解决方案

sed 'G;s/;/\n/' | awk -F= '
$1~/apiKey/ {key=$2}
$1~/term/ {term=$2}
/^$/ {printf("  apiKey=%s term=%s\n", key, term)
      key=""
      term=""}'

首先 sed 用于做两件事:“G”命令将在每个“记录集”之后有效地添加一个开放行,其次“替换”命令(s/;/\n/)将有效地将每个记录集扩展为每行一个;用换行符替换每个字符。 sed 产生的是每行一个键值对,并用一个空行指定每条记录的结尾。

那么 awk 只需要查看第一个字段来查找您感兴趣的属性,然后查看第二个字段来查找值,这样就不需要索引和 substr 了。一旦 awk 遇到“空行”,它就会打印找到的值。为了恢复能力,您可以“清除”每条记录末尾的值。请注意使用 来-F=指示 awk 根据=- 符号将行拆分为字段。

$1 ~ /.../意思是“当第一个字段与值匹配时/.../

然后它为变量(键或术语)分配一个值

意思/^$/是“当 awk 遇到空行时”

答案3

它可能不是很有效,但是如果您想追求“两个 grep”方法,您可以使用paste

$ paste <(grep -o 'apiKey=[^;]*' dummyKeyAndValue.txt) <(grep -o 'term=[^;]*' dummyKeyAndValue.txt)
apiKey=key1     term=abc
apiKey=key2     term=def
apiKey=key1     term=pqr
apiKey=key3     term=def

或者使用 GNU 的 KISS 方法sed

sed -nE -e 's/(apiKey=[^;]*).*(term=[^;]*)/\1 \2/p' \
  -e 's/(term=[^;]*).*(apiKey=[^;]*)/\2 \1/p' dummyKeyAndValue.txt

相关内容