Como afirmar que uma string tem um caractere de nova linha e, em caso afirmativo, remova-a

9

Eu tenho uma string que é o resultado de alguma operação sobre a qual não tenho controle. Quando imprimo esta variável usando echo , recebo:

echo $myvar
hello

No entanto, quando faço

if [ $myvar = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi

Eu sempre entendo que eles não são iguais. Eu suspeito que isso é por causa de um caractere newline .

A string também se comporta de maneira estranha. Quando eu faço:

newVAR="this is my var twice: "$myvar$myvar
echo $newVAR

Eu recebo:

hellois my var twice: hello

Como posso verificar se, de fato, isso é devido a um newline e, em caso afirmativo, removê-lo?

    
por farid99 10.07.2015 / 00:54

4 respostas

8

O problema é que você tem um Carriage-Return incorporado (CR, \r ). Isso faz com que o ponto de inserção de texto do terminal retroceda até o início da linha que está sendo impressa. É por isso que você está vendo o 'olá' no início da linha em você $newVAR example - sed -n l exibe uma visualização legível de caracteres não imprimíveis (e fim de linha).

var=ab$'\r'c ; echo "$var";  printf %s "$var" | sed -n l
# output:
cb
ab\rc$

Você pode testá-lo com uma simples verificação de condição bash:

[[ $var == *$'\r'* ]] && echo yes || echo no
# output:
yes

Você pode combinar o teste e corrigir em uma etapa testando \r (s) e removendo-os por:

fix="${var//$'\r'/}"; echo "$var"; echo "$fix"
# output:
cb
abc

A correção usa Expansão do Parâmetro da Shell . O formulário específico usado acima é para substituir substrings com base no seu padrão fornecido: ${parameter/pattern/string} < -  Isso substitui apenas o primeiro padrão encontrado por string na variável * parâmetro. Para substituir todos padrões, basta alterar o primeiro / para // .

    
por 10.07.2015 / 01:15
5

Você pode representar \r como $'\r' no bash:

if [ "$myvar" = "hello"$'\r' ]; then
    echo they are equal
else
    echo they are not equal
fi

Ou corte o último \r em myvar :

if [ "${myvar%$'\r'*}" = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi
    
por 10.07.2015 / 01:10
3

Curiosamente, em muitos shells getopts é um candidato muito provável para um trabalho como este. Isso pode parecer contra-intuitivo no começo, mas se você considerar que a função principal getopts 'é reconhecer e oferecer interpretação como muitas opções de linha de comando de caractere único especificadas, como pode ser encontrado em uma série concatenada do mesmo, pode começar faça um pouco mais de sentido.

Para demonstrar, a partir de um shell bash :

x=$(printf '\n\r%010s\t' hello)
OPTIND=1
while  getopts : na "-$x"
do     printf %q\n "$OPTARG"
done
$'\n'
$'\r'
\
\
\
\
\
h
e
l
l
o
$'\t'

Dessa forma, às vezes pode ser conveniente permitir que getopts manipule a desmontagem como uma espécie de piloto automático de shell para casos como esse. Ao fazer isso, você pode simplesmente excluir bytes indesejados com case ou [ test ] e criar o backup de seqüência de caracteres a partir do byte 1:

OPTIND=1 y=$(printf \n\r) z=
while  getopts : na "-$x"
do     case $OPTARG in ([!$y])
            z=$z$OPTARG
       esac
done
printf %q\n "$z"
$'     hello\t'

Dado este caso simples de exemplo - e dado um shell que suporta as expansões de parâmetros já mencionadas anteriormente -, as expansões provavelmente servirão melhor para você aqui. Mas eu achei que getopts valeria a pena mencionar também, caso você não estivesse ciente de suas capacidades a esse respeito. Certamente, quando soube disso, encontrei muitos aplicativos úteis para isso, de qualquer forma.

    
por 10.07.2015 / 06:38
0

Embora o Bash e outras linguagens shell sejam úteis, às vezes é melhor usar uma linguagem de script verdadeira - como o Perl. O Perl pode substituir scripts de shell que chamam outros idiomas, como sed e awk, bem como comandos do UNIX com bastante facilidade. Aprendi isso há mais de 20 anos quando escrevi scripts C-Shell que, por sua vez, chamavam sed, awk e vários comandos UNIX - antes de chamar o código FORTRAN. Em Perl eu faria:

chomp($myvar);   # removes the newline char

if("$myvar" eq "hello")   # string comparison
  {
  print "they are equal\n";
  }
else
  {
  print "they are not equal\n";
  }
    
por 20.07.2015 / 22:05

Tags