faz a saída do grep sem arrastar a nova linha

8

Por favor, considere este trecho:

X=$(grep -m1 'some-pattern' some-file | sed -n 's/.* //p')

Eu quero colocar a última palavra em uma variável se alguma condição padrão for correspondida por linhas no arquivo de texto arbitrário

Meu problema é que a variável X tem CR ou LF ou CRLF no final, dependendo do arquivo de origem, do qual eu quero me livrar, pois interfere na operação posterior que pretendo fazer.
Eu até tentei algo como:

X=$(grep -m1 'some-pattern' some-file | sed -n 's/.* \([A-Za-z]\+\)//p')

, portanto, esperando que a saída sed seja limitada em [A-Za-z]+ , mas ainda existem bytes incômodos dentro da variável X.

Como posso me livrar dele, sem usar muito código, como ver quais bytes estão no final com xxd e cut e complicações semelhantes?

    
por zetah 03.03.2012 / 02:05

6 respostas

4

Parece que awk seria a melhor opção para suas necessidades, pois esses problemas não existem devido ao fato de poder usar campos e registros:

x=$(awk '/some-pattern/ { sub(/\r$/, "") ; printf("%s", $NF) ; exit }' some-file)

A substituição evita seu problema com finais de linha CRLF.

sub(/\r$/, "") remove o CR final, se existir. Como awk trata \n como o separador de registro (linha), não é necessário separá-lo, pois ele não está nos dados que estão sendo observados.

printf("%s", $NF) imprime o campo final ( $NF ) sem nova linha à direita ( print e algumas outras funções awk acrescentam uma nova linha por padrão).

exit acontece após as duas primeiras ações - isso equivale a m1 na linha de comando grep . Isso garante que awk saia após a execução dos dois comandos anteriores - e como esses comandos são emitidos em uma correspondência, e awk avalia os dados de uma maneira FIFO, isso somente imprimirá a primeira correspondência.

    
por 03.03.2012 / 02:15
7

O '' ou $() removerá a nova linha do final, mas para fazer isso programaticamente, use tr .

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d '25'

Isso removerá o retorno de carro e / ou a nova linha da string.

O que pode ser o problema é como você, em seguida, envia o resultado . Por exemplo, por padrão, echo adiciona uma nova linha. Você pode querer usar echo -n ou printf .

    
por 03.03.2012 / 03:01
3

Eu prefiro assim

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d '\n'
    
por 14.07.2012 / 00:11
2

Isso funciona para mim:

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d "\n" | tr -d "\r"
    
por 07.08.2012 / 06:42
0

Por que não simplesmente deixar sed fazer a [\r\f] cleanup:

# using Bash's $'string' idiom (that decodes ANSI C escape sequences)
# cf. http://wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
- X="$(grep -m1 'some-pattern' some-file | sed -n 's/.* //p')"
+ X="$(grep -m1 'some-pattern' some-file | sed -n -e $'s/[\r\f]*$//' -e 's/.* //p')"

Sua segunda abordagem não possui um regex final para capturar o CR à direita, \r .

# sample code to remove trailing \r with sed
# cf. http://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes
printf 'a b c\r' | sed -n 's/^.* \([[:alpha:]]\{1,\}\)//p' | od -c
printf 'a b c\r' | sed -n 's/^.* \([[:alpha:]]\{1,\}\)[[:space:]]*//p' | od -c

# keeps trailing space after c
printf 'a b c \r' | sed -n 's/^.* \([[:alpha:] ]\{1,\}\)[[:space:]]*//p' | od -b
    
por 09.04.2013 / 12:53
0

A versão normal do grep (incluindo grep -P) sempre produz um feed de linha com sua correspondência, portanto, se você tiver apenas um resultado (ou desejar que o feed de linha adicionado final seja removido), basta remover o caractere final da saída, que você pode fazer canalizando-o em head -c-1 .

    
por 13.05.2015 / 15:23

Tags