我有一个输入文件如下:
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