使用 awk、sed、grep 对输入进行分组

使用 awk、sed、grep 对输入进行分组

我有一个输入文件如下:

1001   Ivanov I.I: chess 
2021   Petrov P.P: chess, football
3352   Sidorov S.S:  
1000   Putin V.V: judo
8773   Schwarzenegger A: judo, chess, football

我期望输出如下:

-- chess -- 
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V.
  Schwarzenegger A

答案1

这是一个丑陋的“oneliner”,它完全按照您在问题中指定的方式完成工作。

for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/ <p>/' | sed 's/$/<\/p>/'; done;

然而,我写这篇文章不仅仅是为了帮助您解决这个精确的问题:我特意将解决方案写成执行非常具体的操作的部分,下面是对这些部分的作用的解释。所以如果你想学习除了解决这个特定问题之外,如何使用这些工具,请继续阅读!

让我们一点一点地看看它是如何工作的:

for tag in- 为我们定义了一个名为 的新变量tag。这用于您需要的标签。

cat input- 读取名为 的文件input,将此名称更改为您的文件名。

|是一个管道;一种通过一系列命令获取数据的有趣方式。

cut -d: -f2- 使用冒号:作为分隔符,取第二个字段。这会在每行的冒号后面显示文本。

sed 's/<\/p>//g'- 删除输入的每一行上的结束段落标记。

此时,数据将如下所示:

 chess 
 chess, football

 judo
 judo, chess, football

接下来,让我们删除仅由空格组成的空行,因为有些人没有与其关联的标签。

sed '/^[[:space:]]*$/d'- 删除所有只有空格的行。伟大的!

tr "," "\\n"- 用换行符替换所有逗号,以便每个标签将位于单独的行上。

sed 's/[[:space:]]//g'- 删除行开头的任何额外空格

sort -u- 按字母顺序对标签进行排序,并删除任何重复项。现在我们有了所有标签的完美列表,按顺序排列,并且没有重复:

chess
football
judo

现在,对于每个对于这些标签,我们一个接一个地执行以下操作:

echo "<p>-- $tag --</p>"- 按照指定打印段落 html 标签、两个破折号、标签名称、两个破折号和一个结束段落标签。

grep $tag input- 查找具有特定标签的行

awk '{print $2, $3}'- 打印姓名字段(姓氏+姓名缩写)

sed 's/://g'- 删除 awk 认为是缩写的一部分的冒号

sed 's/^/ <p>/'- 在每行的开头添加段落标签

sed 's/$/<\/p>/'- 在每行末尾添加一个结束段落标签

done;- 我们就完成了,耶!

结果如下:

$ for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/  <p>/' | sed 's/$/<\/p>/'; done;
<p>-- chess --</p>
  <p>Ivanov I.I</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- football --</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- judo --</p>
  <p>Putin V.V</p>
  <p>Schwarzenegger A</p>

编辑:有人提到标签不是输入的一部分。这稍微简化了事情:

$ for tag in `cat input |cut -d: -f2 |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "--$tag --"; grep $tag input | awk '{print $2, $3}' | sed 's/://g'; done; 
--chess --                                                        
Ivanov I.I
Petrov P.P
Schwarzenegger A
--football --
Petrov P.P
Schwarzenegger A
--judo --
Putin V.V
Schwarzenegger A

答案2

awk -F: '{
    sub( "[ 0-9]+", "", $1 )
    gsub( " +", "", $2 )
    cz=split( $2,comp,"," )
    for( c=1; c<=cz; c++ ) {
        if( comp[c] ) {
            if( ! allcomp[comp[c]] ) 
                fifocomp[++fifoc] = comp[c]
            allcomp[comp[c]] = allcomp[comp[c]] "  " $1 "\n" 
        }
    }
} END {
    for( c=1; c<=fifoc; c++ ) {
        print "-- " fifocomp[c] " --"
        printf "%s", allcomp[fifocomp[c]]
    }
}' file

输出:

-- chess --
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V
  Schwarzenegger A

相关内容