corte para pares de valores-chave

6

Estou procurando uma maneira fácil de cortar pares de valores-chave (em que a chave é única e especificada) do texto, da mesma forma como cut pode ser usado para cortar uma coluna especificada em um arquivo CSV. As chaves que estou procurando nem sempre estão na mesma posição relativa na linha - isto é, usar cut seguido por sed não vai funcionar, porque a chave que estou procurando nem sempre é na mesma coluna , -delimited.

O texto em questão é, de fato, CSV, mas acontece que os valores são pares chave / valor, delimitados por = .

Por exemplo, posso analisar um arquivo com as três linhas a seguir:

Foo=1, Bar=2, Baz=3
Bar=4, Foo=2, Baz=3
Bar=42, Baz=42, Foo=3

Eu gostaria de cortar este texto para gerar o par chave / valor para uma chave específica. Se eu estivesse procurando Foo , minha saída desejada seria:

Foo=1
Foo=2
Foo=3

O ideal é que eu queira uma ferramenta de linha de comando com sintaxe semelhante a cut e possa ler a partir de stdin e de um arquivo.

Existe tal ferramenta?

    
por John Dibling 23.02.2015 / 23:13

5 respostas

8

grep pode fazer isso com a opção -o :

grep -o 'Foo=[^,]*' file
    
por 23.02.2015 / 23:21
3

A solução awk para arredondar a lista de alternativas:

awk -v RS=', ' -F'=' '$1=="Foo"' <file>

Trate cada registro a ser delimitado por ', ' e divida cada registro em campos no caractere = (usando -F ) também. Então é só uma questão de correspondência no primeiro campo $1 . A sugestão mostrada aqui é uma correspondência de string simples, sinta-se à vontade para usar regexes, por exemplo $1~/\<Foo\>/ .

    
por 24.02.2015 / 03:23
2

Dependendo da complexidade da sua situação do mundo real, esse comando sed pode ser suficiente:

sed -n 's/^.*\(\<Foo=[^,]*\).*//p'

Aqui está o exemplo trabalhado

FIELD='Foo'
sed -n "s/^.*\(\<${FIELD}=[^,]*\).*//p' << xxEOFxx
Foo=1, Bar=2, Baz=3
Bar=4, Foo=2, Baz=3
Bar=42, Baz=42, Foo=3
xxEOFxx
Foo=1
Foo=2
Foo=3
    
por 23.02.2015 / 23:21
2

Dado seu exemplo, uma solução frágil poderia envolver cut :

tr ', ' '[\n*]' <input | cut -sd F -f1-

... o qual colocaria cada par de chave / valor em uma linha separada por tr , formando as vírgulas e espaços intervenientes em \n ewlines e, em seguida, cut linhas que não contêm F . Mas esse é um exemplo altamente especializado e só pode funcionar se você puder ter certeza de que um F ocorre apenas nos pares de chave / valor desejados.

Caso contrário, sed seria o que eu usaria:

sed 'y/ ,/\n\n/;/^Foo=/P;D' <input

Que também tr apresentará vírgulas e espaços de intervenção em \n ewlines, mas somente P rint os pares de chave / valor que começam com a string Foo= . Contanto que os espaços sejam separadores confiáveis, os itens acima funcionariam para portavelmente imprimir os pares% chave / valor Foo em uma linha separada, não importando quantas vezes eles pudessem ocorrer em uma linha de entrada, e imprimissem mais nada - mesmo para linhas que não contêm a chave / valores que você deseja imprimir.

    
por 23.02.2015 / 23:26
1

Se você não tiver um grep disponível com a opção -o , isso também funcionará:

sed -e 's/, /\n/g' | grep '^Foo='

Isso está usando sed para substituir cada vírgula + espaço por uma nova linha (dividindo cada par de valores-chave em sua própria linha) e, em seguida, grep para procurar apenas a chave "Foo".

Caso de teste:

printf "%s\n" "Foo=1, Bar=2, Baz=3" "Bar=4, Foo=2, Baz=3" "Bar=42, Baz=42, Foo=3" \
    | sed -e 's/, /\n/g' | grep '^Foo='
    
por 23.02.2015 / 23:29