我试图在基于相同名称的文件上插入换行符,这恰好是我文件中的第二个字段。所以,我的输入文件如下所示。
17412193|name1|organization
43979400|name1|organization
1405541|name2|organization
53595498|name2|organization
50439202|name2|organization
54678379|name3|Not Found
21757330|name3|organization
所以我试图得到这样的输出,
17412193|name1|organization
43979400|name1|organization
###linebreak inserted here
1405541|name2|organization
53595498|name2|organization
50439202|name2|organization
###linebreak inserted here
54678379|name3|Not Found
21757330|name3|organization
###linebreak inserted here
我使用这个换行符来分割输入文件,将相似的名称分组在一起。我稍后会对这些分组名称应用相似性算法。因此,对于上面的示例,在输出之后,我将对 3 对名称应用相似度算法。
答案1
假设您的文件已按第二个字段排序/分组
awk -F '|' 'NR>1 && $2 != prev {print ""} {prev=$2; print}' file
答案2
这是一个不区分大小写的 Perl 解决方案:
perl -F'\|' -lape 'unless($F[1]=~/^$pre$/i || $.==1){print ""}; $pre=$F[1]' file
解释:
- 将
-a
输入行分割到@F
数组中,使 Perl 的行为类似于 awk。 - 是
-F
字段分隔符 -p
表示打印每个输入行-l
\n
向每个打印调用添加一个,因此print ""
打印换行符。unless($F[1]=~/^$pre$/i || $.==1)
:除非第二个字段与前一行相同(i
in//i
使匹配不区分大小写),或者除非这是第一行。$pre=$F[1]
:将此行第二个字段保存为$pre
.
@GlennJackman 在评论中建议了一个稍微不同的版本,对于较大的文件来说可能会更快:
perl -F'\|' -lape 'unless(lc($F[1]) eq lc($pre) || $.==1){print ""}; $pre=$F[1]' file
答案3
更短的 Perl 解决方案:
perl -pe 'print "\n" if ($l =~ /name\d+/ && $_ !~ /$&/);$l=$_;' input
- 如果最后一行 (
$l
)name\d+
与当前行不是最后匹配的,则打印新行 - 将当前行分配给
$l
更通用的解决方案
perl -pe 'print "\n" if ($l =~ /\|([^\|]+)/ && $_ !~ /$1/);$l=$_;' input
答案4
#!/bin/sh
#shell basics, POSIX compliant
(set -f ;IFS='|
' ; set -- $(cat) ; while [ -n "$3" ] ;do {
[ "${t=$2}" != "$2" ] && echo && t=$2
printf '%s|%s|%s\n' "$1" "$2" "$3" ; shift 3
} ; done )<<\SAMPLE
17412193|name1|organization
43979400|name1|organization
1405541|name2|organization
53595498|name2|organization
50439202|name2|organization
54678379|name3|Not Found
21757330|name3|organization
SAMPLE
Output
17412193|name1|organization
43979400|name1|organization
1405541|name2|organization
53595498|name2|organization
50439202|name2|organization
54678379|name3|Not Found
21757330|name3|organization