Imprime variável com barras invertidas no traço

1

Minha concha é traço. Meu problema é o seguinte:

# A="abc\nde fg"
# printf "$A"
abc
de fg#

# B="abc\nde fg"
# printf "$B"
abc
de fg#

# C="abc\\nde fg"
# printf "$C"
abc\nde fg# 

A variável de string com a qual estou trabalhando tem espaços e \n e possivelmente outros caracteres de espaço em branco. Gostaria de acessar a variável $A sem escapar do \n na string. Usar aspas simples não o interpretaria como uma variável e, usando aspas duplas, interpreta esses caracteres especiais.

O traço tem um caminho embutido no shell para fazer isso? Eu sei que posso enviar a variável para um programa externo que irá duplicar as barras invertidas para os caracteres de escape na string, mas isso parece errado.

EDITAR:

Eu percebo meu erro com printf , mas não está relacionado neste caso. Inicialmente eu estava usando echo . Este é um exemplo melhor do que estou perguntando. Aqui estão duas das mesmas sequências de comandos, apenas a primeira é em bash e a segunda é em traço:

bash

$ cat sample.txt
abc\nde fg

some string

$ A='cat sample.txt'
$ echo "$A"
abc\nde fg

some string
$ 

traço

$ cat sample.txt
abc\nde fg

some string

$ A='cat sample.txt'
$ echo "$A"
abc
de fg

some string
$ 

Gostaria de saber se posso ter traço não interpretar o \n nessa seqüência de comandos. Eu já implementei uma solução alternativa usando um comando externo. O uso adequado de printf faz o que eu quero, mas estou curioso para ver se o próprio painel tem alguma maneira de fazer isso sozinho.

Aqui está a razão pela qual a pergunta surgiu, por completo. Eu preciso ler um arquivo e comentar ou descomentar a parte inferior. A primeira parte tem um literal \n (não newline) que precisa ficar assim no arquivo reescrito.

Eu divido o arquivo em 2 partes usando o sed contido nos backticks e os atribuo às variáveis. No final, concateno as variáveis simplesmente fazendo algo como "$VAR1$VAR2" , em que $VAR2 já foi condicionalmente comentado, descomentado ou deixado sozinho.

    
por Joshua Marshall 09.12.2016 / 18:10

3 respostas

2

Seu problema é que Bash e Dash têm echo como internos, mas as duas implementações não se comportam da mesma forma quando recebem uma string contendo \ :

echo 'abc\ndef'

Isso produz resultados diferentes nas duas camadas.

Você pode obter resultados consistentes usando printf '%s\n' ; embora isso também seja interno, produz a mesma saída em ambos os shells (isso não é verdadeiro para todas as conversões, por exemplo, bash fornece uma %q conversion que traço não faz):

printf '%s\n' 'abc\ndef'

Isso produz abc\ndef em ambos os shells.

Você pode alternativamente usar uma implementação externa de echo ; no Linux, coreutils fornece o eco GNU em /bin/echo :

/bin/echo 'abc\ndef'

Note, no entanto, que isso é menos portável. O arquivo info do GNU tem isto a dizer:

POSIX does not require support for any options, and says that the behavior of echo is implementation-defined if any string contains a backslash or if the first argument is -n. Portable programs can use the printf command if they need to omit trailing newlines or output control characters or backslashes.

    
por 13.12.2016 / 17:23
4

Não, existem muitas variantes de echo . echo não é um comando portátil.

dash echo é, na verdade, uma das poucas implementações echo que são compatíveis com UNIX (a esse respeito pelo menos; dash não é multi-byte ciente, existem outras áreas em que não é compatível em sistemas que suportam localidades multi-byte, por exemplo).

A especificação do UNIX requer

echo '\n'

para gerar dois caracteres de nova linha e

echo -e x

para gerar -e x<newline> .

Enquanto alguns outros shells como AT & T ksh , bash , yash ou zsh têm configurações para alterar o comportamento de seus echo embutidos (o comportamento do comando GNU echo também pode afetado pelo ambiente), atualmente não é o caso de dash .

Em qualquer caso, você não quer usar echo para enviar dados arbitrários. O comando padrão e portátil para isso é printf .

Você pode encontrar mais detalhes, incluindo como implementar um echo diferente como uma função wrapper em torno de printf na resposta para Por que printf é melhor que echo?

    
por 13.12.2016 / 17:11
2

Você está usando printf com sua variável como a string de formatação em vez de ser um valor interpolado pela string de formatação.

Use echo ou use printf da maneira pretendida. Aqui estão alguns exemplos:

A="abc\nde fg" B="abc\nde fg" C="abc\\nde fg"
echo "$A"
abc\nde fg

echo "$B"
abc\nde fg

echo "$C"
abc\nde fg

printf "%s\n" "$A"
abc\nde fg

printf "Here is variable B: %s\n" "$B"
Here is variable B: abc\nde fg

printf "> %s <\n" "$C"
> abc\nde fg <

Por acaso, usando cadeias duplas entre aspas, elas são analisadas e o caractere de barra invertida \ é processado. Se você definir as variáveis com strings entre aspas simples, todo o conjunto de caracteres \ também poderá ser preservado:

A='abc\nde fg' B='abc\nde fg' C='abc\\nde fg'

echo "$A"
abc\nde fg

echo "$B"
abc\nde fg

echo "$C"
abc\\nde fg
    
por 11.12.2016 / 01:04