Maneira de remover nova linha (^ M) apenas de variáveis, não de arquivo

5

Estou carregando um arquivo em variáveis, o problema é que o arquivo está formatado no Windows, acredito, então eu recebo um ^M em vez de uma nova linha.

Como modifico quando o valor está na variável? Estou ciente de que posso modificar a fonte no VI (eu uso o OS X, a propósito), mas não posso modificar o arquivo original, apenas lê-lo, então eu tenho que remover o ^M da variável. / p>

Pelo que entendi, \n não é o mesmo que ^M , então o comando tr não funcionará.

EDITAR

Parece que a questão não está clara; então esse é o esclarecimento.

Eu analiso o arquivo linha por linha; cada linha tem 2 valores, separados por tab e no final de cada linha, há um ^ M, é assim:

value1    value2^M
value3    value4^M
value5    value6^M
value7    value8^M

Meu fluxo de trabalho é bastante direto e simples: o arquivo txt contém o que você vê acima, os campos separados por loop e para cada linha obtém os valores; quando eu imprimir o segundo valor, ele tem o ^ M, que eu gostaria de remover

while IFS=$'\t' read -r -a line
do
    Type1="${line[0]}"
    Type2="${line[1]}"
done < $TXTFILE

O que significa que quando imprimo Type1 está bem, mas a variável Type2 contém o ^ M. Eu usei tr e não funcionou, usei sed para remover o último caractere da variável e não funcionou. Espero que isso esclareça a minha pergunta. Obrigado

    
por rataplan 26.11.2016 / 03:13

4 respostas

4

^M é um retorno de carro (CR), que pode ser especificado como \r para tr ou dentro de $'…' . \n especifica um feed de linha (LF), que é ^J . Uma terminação de linha Unix é LF e um separador de linha do Windows é a sequência de dois caracteres CR-LF, portanto, arquivos de texto do Windows exibidos em um sistema Unix como Linux ou macOS parecem ter ^M no final de cada linha, exceto na última linha que está faltando sua nova linha final.

Você pode remover retornos de carro de um arquivo com tr com

tr -d '\r' <somefile.txt >somefile.txt.new && mv somefile.txt.new somefile.txt

ou mais simplesmente com dos2unix .

Para evitar a modificação dos arquivos, você pode verificar cada linha ao lê-la e desmarcar CR no final de uma linha. Por exemplo, se você estiver usando read para analisar valores separados por tabulações, desmarque CR no final do último campo. A expansão de parâmetro ${VAR%$'\r'} produz o valor de VAR menos um CR à direita e gera o valor de VAR se não terminar com CR.

while IFS=$'\t' read -r -a line
do
    line[$((${#line[@]}-1))]="${line[$((${#line[@]}-1))]%$'\r'}"
    Type1="${line[0]}"
    Type2="${line[1]}"
done < "$TXTFILE"
    
por 27.11.2016 / 00:33
6

Aqui está a maneira mais simples de corrigir seu script, basta adicionar "retorno de carro" como um separador de campo interno para o comando de leitura:

while IFS=$'\t\r' read -r -a line
do
  Type1="${line[0]}"
  Type2="${line[1]}"
done < $TXTFILE
    
por 26.11.2016 / 11:23
3

Use (para strings curtas):

${var//$'5'}

Exemplo:

$ var=$'This is a test of a CR (\r) character'
$ echo "${var//$'\r'}"
This is a test of a CR () character

Para strings mais longas, você pode precisar de sed ou awk.

    
por 26.11.2016 / 10:57
0

Uma maneira geralmente mais útil de converter o conteúdo de arquivos "DOS", que não têm outro marcador de conteúdo do que ter terminações de linha CR + LF (em contraste apenas com o Linux LF).

Para o Ubuntu, primeiro e apenas uma vez, faça

sudo apt install dos2unix

o uso conforme indicado abaixo, aqui com od usado para verificar a saída

$ dos2unix < $TXTFILE | od -t x1z -w17 
0000000 76 61 6c 75 65 31 20 20 20 20 76 61 6c 75 65 32 0a  >value1    value2.<
0000021 76 61 6c 75 65 33 20 20 20 20 76 61 6c 75 65 34 0a  >value3    value4.<
0000042 76 61 6c 75 65 35 20 20 20 20 76 61 6c 75 65 36 0a  >value5    value6.<
0000063 76 61 6c 75 65 37 20 20 20 20 76 61 6c 75 65 38 0a  >value7    value8.<
0000104

$ cat $TXTFILE | od -t x1z -w18
0000000 76 61 6c 75 65 31 20 20 20 20 76 61 6c 75 65 32 0d 0a  >value1    value2..<
0000022 76 61 6c 75 65 33 20 20 20 20 76 61 6c 75 65 34 0d 0a  >value3    value4..<
0000044 76 61 6c 75 65 35 20 20 20 20 76 61 6c 75 65 36 0d 0a  >value5    value6..<
0000066 76 61 6c 75 65 37 20 20 20 20 76 61 6c 75 65 38 0d 0a  >value7    value8..<
0000110

Isso irá traduzir não apenas os finais de linha, mas também outros caracteres especiais, dependendo dos parâmetros para dos2unix ou sua contraparte unix2dos (que é instalada ao mesmo tempo).

    
por 26.11.2016 / 13:35