Não tenho certeza de como formular a pergunta, pois a maioria das respostas é sobre a remoção \r\n
de um arquivo.
Eu tenho um problema único em que os arquivos compactados são numerados aleatoriamente e, para associá-los adequadamente a um registro do banco de dados, preciso listar o conteúdo do arquivo e verificá-lo.
Estou usando essas soluções "No script bash, como capturar stdout linha por linha"
O que foi um ótimo começo.
Alguns dos conteúdos têm um nome com espaço em branco e encontrei esta solução: Como imprimir a terceira coluna na última coluna?
Descobri ao tentar atualizar o registro do banco de dados, que ^M
está sendo inserido nos resultados do awk
pipe, mas apenas para a NF
coluna.
Não tenho certeza de como resolver essa falha específica. Não vejo onde ^M
está sendo inserido, ou como removê-lo da última coluna.
Meu código
Esta linha funciona bem se eu tirar^M
filename="$(echo "$line" | awk '{if ($3 ~ /^M$/) {sub(/^M$/,"", $3)} printf $3; printf ""}')"
Esta linha falha:
text="$(echo "$line" | awk '{for(i=6;i<NF+1;i++) {if ($i ~ /^M$/) {sub(/^M$/,"", $i)} } printf "%s ", $i; printf ""}')"
E a versão simplificada falha:
text="$(echo "$line" | awk '{for(i=6;i<NF+1;i++) sub(/^M$/,"", $i) printf "%s ", $i; printf ""}')"
In vim
/ vi
^M
é criado com ctrl-V + <return key>
Using \r\n
não tem efeito.
Estou usando cygwin
, e tenho usado há muito tempo, e tenho outros *nix
scripts que escrevi que funcionam bem. Descobri que, por algum motivo, essa execução específica awk
está aumentando ^M
a saída.
Encontrei esta pergunta com um problema semelhante, mas criei meu script vim
desde o início, para que não houvesse editor baseado em janelas envolvido.
Se eu montar essa pasta do Windows como um compartilhamento de samba e executar o script do linux, ele produzirá a saída sem um ^M
, então neste momento estou me perguntando se isso é um bug ou outra coisa. É realmente estranho.
UPDATE Meu uso do REGEX em sub() estava fazendo com que a string retornasse vazia, então não entendi corretamente como limpar o CRLF.
NF+1 foi um resquício da tentativa de descobrir o que estava introduzindo o CRLF que eu estava usando i<=NF antes disso.
Com algumas implementações
awk
incluindo GNUawk
emawk
busyboxawk
(as 3 implementações comumente encontradas em sistemas baseados em Linux, Cygwin sendo GNUawk
por padrão, acredito),RS
o separador de registro de entrada pode ser uma expressão regular (em oposição a um único caractere em POSIX) .Neles, você pode fazer:
para processar esses arquivos, ou:
para poder processar ambos os arquivos com
\n
delimitadores ou\r\n
separadores.alguns arquivos do MS-DOS também tendem a ter a última linha não delimitada, mas
awk
também corrigirão isso na saída, pois anexa o separador de registro de saída (ORS
que permanece\n
aqui) a todos os registros durante a impressão.No que diz respeito à divisão de campo padrão
awk
, você também descobrirá que há variação entre as implementações. POSIX diz que deve ser dividido em sequências de espaços em branco , à esquerda e à direita removidos. A noção de espaço em branco depende da localidade e inclui pelo menos SPC e TAB. Você encontrará muitasawk
implementações que o restringem apenas a SPC e TAB, independentemente da localidade, muitas também adicionam NL (relevante apenas quando o separador de registro não é nova linha).busybox
awk inclui todos os espaços em branco ASCII, incluindoCR
,FF
,VT
. Portanto, no busyboxawk
, os campos por padrão nunca contêm CR. Você pode obter o mesmo comportamento com o GNUawk
fazendogawk -v 'FPAT=[^[:space:]]'
where os campos são definidos como sequências de não espaços em branco.Mais algumas notas:
awk
que é uma das ferramentas certas para processar texto.echo
em dados arbitráriosprintf
é o formato, você não quer usar dados arbitrários lá. Useprintf "%s", $3
se quiser imprimir$3
sem anexarORS
, não.printf $3
printf ""
é um não-op. Não faz nada. Se você quiser imprimir uma nova linha, useprintf "\n"
ouprint ""
(o último imprimeORS
, nova linha por padrão).awk
não identifica o^M
literalmente, ele o identifica como o padrão CRLF\r\n
, então vocêsub()
pode usar a representação do caractere CR diretamente como abaixo. Além disso, você não precisa verificar se o campo contém um caractere e fazer uma substituição. As funções de substituição simplesmente não fazem nada se o padrão mencionado não for encontrado. Portanto, tudo o que você precisa é o seguinte para substituir o CR apenas na última coluna.Se houver várias colunas que precisam ser substituídas, alterne
$NF
com a coluna apropriada necessária.Se você estiver fazendo isso em um loop para todas as colunas até o final do arquivo, apenas faça
Além disso, o arquivo só pode ter
NF
colunas máximas e$NF
é o último valor da coluna. Altere seu loop para executar atéNF
acessar o último valor da coluna.