Preciso editar a string "NA" para "Na" somente se ela estiver no 6º campo de um arquivo. Atualmente, posso fazer isso com:
awk '{gsub("NA","Na",$6)}1' $filename
No entanto, preciso da condição adicional de que isso não ocorra se a string "HEM" estiver na mesma linha. Por exemplo, eu gostaria que a linha a seguir permanecesse a mesma:
7353 NA 5.4433 24.4404 -3.0784 NA 456 HEM
Por fim, o comando acima remove o preenchimento extra entre os campos. Se houver um comando que possa fazer isso sem alterar o espaçamento entre os campos, isso seria ótimo, mas esse recurso não é necessário.
Acho que isso poderia ser feito lendo cada arquivo e imprimindo cada linha, e editando apenas com uma instrução if, mas estou tentando evitar algo desajeitado como isso.
Sinto que isso é uma tarefa difícil de fazer de forma simples, mas ficaria super grato se algum mago do Unix soubesse como. Obrigado!
Usando GNU awk para o terceiro argumento
match()
e\s
/\S
abreviação:ou usando qualquer awk POSIX:
Usando
gawk
:-- Da Linguagem de Programação AWK
Ou
Com
perl
em vez deawk
:^\s*(\S+\s+){5}\K\S+
correspondes
ao ritmo branco opcional no início, seguido por5
ocorrências de ritmo não brancoS
+ ritmo brancos
, seguido por não espaço em branco (o 6º campo ), que mantemosK
como a correspondência.$& =~ s/NA/Na/gr
ée
avaliado como código perl onde o resultado das
substituição (g
localmente como com seugsub()
) deNA
withNa
no que foi correspondido ($&
) ér
retornado como a substituição do externos{regex}{replacement}e
.Se você não pretendia substituir todas as ocorrências de
NA
dentro do 6º campo , mas apenas substituí-lo porNa
if it wasNA
, então isso pode ser simplificado para:Observe o
(?!\S)
operador negativo de antecipação, que verifica seNA
não é seguido por um espaço em branco, sem o qual ele também seria substituídoNAPOLEON
porNaPOLEON
, por exemplo.Até
sed
faria isso mais facilmente do queawk
lá:Com GNU
sed
ou compatível, você pode usar\s
/\S
como em Perl no lugar de[[:space:]]
/[^[:space:]]
. GNUsed
(e alguns outros, embora às vezes com uma interface incompatível) também suporta edição-i
emi
n lugares à laperl
.-E
agora é padrão e suportado pela maioriased
das implementações. Se você estiver em um sistema muito antigo que não o suporta, você pode alterá-lo para:Uma abordagem mais geral para lidar com campos delimitados por espaços em branco, preservando o espaçamento, é dividir a entrada na lista de campos e strings separadoras de espaços em branco.
Por exemplo, seria dividido em 17 "campos":
Seu 6º campo anterior se tornaria o 12º nessa nova divisão.
Em
perl
(observe que @rrays são indexados a partir de 0, então o 12º campo se torna$F[11]
):Note que permitimos que o primeiro "campo" fique vazio colocando-o em caixa especial com
^\s*
, enquanto todos os outros devem ser não vazios (\s+
para pelo menos um caractere de espaço em branco). Note que noperl -n/-p
modo sed (ou-a
modo wk), a menos que você passe a-l
opção, o delimitador de nova linha é incluído no espaço do padrão ($_
), então ele fará parte do último "campo" de espaço em branco aqui (17º no exemplo acima).