Assumindo que seu arquivo seja classificado / agrupado pelo 2º campo já
awk -F '|' 'NR>1 && $2 != prev {print ""} {prev=$2; print}' file
Estou tentando inserir quebras de linha em um arquivo com base nos mesmos nomes que, por acaso, são o segundo campo do meu arquivo. Então, meu arquivo de entrada é como abaixo.
17412193|name1|organization
43979400|name1|organization
1405541|name2|organization
53595498|name2|organization
50439202|name2|organization
54678379|name3|Not Found
21757330|name3|organization
Então, estou tentando obter a saída como
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
Estou usando essa quebra de linha para dividir o arquivo de entrada para agrupar os nomes semelhantes. Mais tarde eu aplicaria um algoritmo de similaridade nesses nomes agrupados. Então, para o exemplo acima, após a saída eu aplicaria o algoritmo de similaridade em 3 pares de nomes.
Aqui está uma solução de Perl insensível a maiúsculas e minúsculas:
perl -F'\|' -lape 'unless($F[1]=~/^$pre$/i || $.==1){print ""}; $pre=$F[1]' file
Explicação:
-a
divide as linhas de entrada na matriz @F
, fazendo o perl agir como awk. -F
é o separador de campos -p
significa imprimir cada linha de entrada -l
adiciona \n
a cada chamada de impressão, por isso print ""
imprime uma nova linha. unless($F[1]=~/^$pre$/i || $.==1)
: a menos que o segundo campo seja o mesmo da linha anterior (o i
em //i
torna a correspondência insensitiva) ou a menos que seja a primeira linha. $pre=$F[1]
: salve este segundo campo de linhas como $pre
. @GlennJackman sugeriu uma versão ligeiramente diferente nos comentários, que provavelmente será mais rápida para arquivos maiores:
perl -F'\|' -lape 'unless(lc($F[1]) eq lc($pre) || $.==1){print ""}; $pre=$F[1]' file
Uma solução Perl mais curta:
perl -pe 'print "\n" if ($l =~ /name\d+/ && $_ !~ /$&/);$l=$_;' input
$l
) foi name\d+
e a linha atual não corresponde à última, depois imprima nova linha $l
Uma solução mais geral
perl -pe 'print "\n" if ($l =~ /\|([^\|]+)/ && $_ !~ /$1/);$l=$_;' input
#!/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
Tags text-processing awk sed