Substituir todos os valores em uma linha para N / A

1

Estou tentando descobrir como alterar todos os valores em uma linha para N / A. Por exemplo. Eu preciso substituir linhas 77 132 140 142 155 156 157 e 175 com N / A em todas as colunas. Por exemplo:

RS,RPHG,LPHG,RITC
13.7801604545457,3.10785528409178,-38.443658181819,-8.25890473295385
-12.5663095454547,-33.8395547159089,-3.44606818181819,-24.8157817329538
35.1140204545463,-35.4853647159089,-33.8231881818192,26.6855902670459
-29.9357495454533,-34.5783047159075,-50.3323381818191,2.0808182670462
    
por Rachel 27.07.2018 / 19:47

8 respostas

2
$ awk -F, -vOFS=, 'FNR==2 || FNR==4 { for (i=1;i<=NF;++i) $i="N/A" } 1' file
RS,RPHG,LPHG,RITC
N/A,N/A,N/A,N/A
-12.5663095454547,-33.8395547159089,-3.44606818181819,-24.8157817329538
N/A,N/A,N/A,N/A
-29.9357495454533,-34.5783047159075,-50.3323381818191,2.0808182670462

FNR é o número ordinal do registro atual no arquivo atual ("o número da linha no arquivo atual"). Se for dois ou quatro, percorremos todos os campos (de 1 a NF , o número de campos) e definimos cada campo para a string N/A . O trailing 1 no final é uma maneira curta de escrever { print } e fará com que todas as linhas (modificadas ou não) sejam impressas.

Se você tiver um arquivo adicional com todo o número de linha que deve ser removido (um número por linha):

awk -F, -vOFS=, 'FNR==NR { a[$1]; next }
                 FNR in a { for (i=1;i<=NF;++i) $i="N/A" } 1' lines file

Em que lines é o arquivo com números de linha.

Aqui, se FNR==NR estiver lendo o arquivo primeiro (o arquivo lines ). Nesse caso, criamos uma entrada na matriz a com o número da linha como chave e continuamos com a próxima linha. NR é o número total de linhas lidas até agora, e será igual a FNR até começarmos a ler o segundo arquivo.

Se FNR não for igual a NR , então estamos lendo o arquivo segundo (o arquivo file , contendo os dados). Em seguida, testamos se o número da linha atual é uma chave na matriz a e, se for, substituiremos todos os campos como antes por N/A .

    
por 27.07.2018 / 20:08
1

Uma maneira, com sed :

sed '
77c\
N/A,N/A,N/A,N/A
132c\
N/A,N/A,N/A,N/A
140c\
N/A,N/A,N/A,N/A
142c\
N/A,N/A,N/A,N/A
155c\
N/A,N/A,N/A,N/A
156c\
N/A,N/A,N/A,N/A
157c\
N/A,N/A,N/A,N/A
175c\
N/A,N/A,N/A,N/A
' input.csv
    
por 27.07.2018 / 20:04
1

Com para demonstrar com awk filtragem em duas linhas:

awk 'BEGIN { FS=","; OFS="," } { if( NR == 77 || NR == 132 ) {for( i=1; i<=NF; i++) {$NF="N/A"} }; print }' input

Basta adicionar mais opções à declaração if de todas as linhas em questão.

    
por 27.07.2018 / 20:06
1

sed faz isso:

sed '77s/.*/N\/A,N\/A,N\/A,N\/A/;137s/.*/N\/A,N\/A,N\/A,N\/A/;...' YourFile 
    
por 27.07.2018 / 20:07
1

Usando awk :

awk -vOFS=, '{
  if (NR==77 || NR=132 || NR==140 || NR==142 || NR==155 || NR==156 || NR==157 || NR==175)
    $1=$2=$3=$4="N/A"
    print
}' input.csv

Para criar um novo arquivo com a saída, use o operador de redirecionamento > do shell:

awk -vOFS=, '{
      if (NR==77 || NR=132 || NR==140 || NR==142 || NR==155 || NR==156 || NR==157 || NR==175)
        $1=$2=$3=$4="N/A"
        print
    }' input.csv > newfile.csv
    
por 27.07.2018 / 20:05
1
perl -F, -pale '
   $_ = join ",", qw[N/A] x @F
      if grep /^$.$/, qw/77 132 140 142 155 156 157  175/;
' input.csv

Ou com GNU sed , poderíamos fazer usando uma mistura de variáveis de shell:

# give the rows to be made N/A in a comma separated fashion
rows2na='77,132,140,142,155,156,157,175'
b2sub=$(echo "$rows2na," | sed -e 's/,/ba\n/g')
sed -e "
    $b2sub
    b
    :a;s|[^,]*|N/A|g
" input.csv

Nota:

  1. Assegure-se de que o arquivo csv de entrada realmente seja separado por vírgulas e não qualquer outro caractere, digamos, uma TAB.
  2. Verifique se o arquivo de entrada possui terminações de linha unix (o linefeed aka, nova linha "\ n") e não o windows ou o mac.
por 28.07.2018 / 10:54
0

Outra maneira com sed

sed -E '
# for each needed rows jump to A
  77bA
  132bA
  140bA
  142bA
  155bA
  156bA
  157bA
  175bA
  b
  :A
# if the line is empty do nothing
    /^$/b
# Add comma at end of line
    s/$/,/
# Remove each not comma
    s/[^,]//g
# Substitute each comma by N/A,
    s/,/N\/A,/g
# Remove the last comma
    s/,$//
' infile
    
por 28.07.2018 / 11:30
0

bash: isso será lento

n=0
IFS=,
while read -ra fields; do
    case $((++n)) in
        77|132|140|142|155|156|157|175)
            for ((i=0; i<${#fields[@]}; i++)); do fields[i]="N/A"; done
            ;;
    esac
    echo "${fields[*]}"
done < file
    
por 30.07.2018 / 16:28