AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 785831
Accepted
CPC_92
CPC_92
Asked: 2024-10-30 07:42:18 +0800 CST2024-10-30 07:42:18 +0800 CST 2024-10-30 07:42:18 +0800 CST

Como editar uma string que corresponde a um padrão em um campo específico na condição de que outra string não esteja presente na mesma linha

  • 772

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!

awk
  • 3 3 respostas
  • 125 Views

3 respostas

  • Voted
  1. Ed Morton
    2024-10-30T07:52:18+08:002024-10-30T07:52:18+08:00

    Usando GNU awk para o terceiro argumento match()e \s/ \Sabreviação:

    awk '!/HEM/ && match($0,/^((\S+\s+){5})NA(\s.*)/,a){ $0=a[1] "Na" a[3] } 1' file
    

    ou usando qualquer awk POSIX:

    awk '!/HEM/ && match($0,/([^[:space:]]+[[:space:]]+){5}NA[[:space:]]/){ $0=substr($0,1,RLENGTH-3) "Na" substr($0,RLENGTH) } 1' file
    
    • 1
  2. Prabhjot Singh
    2024-10-30T17:12:16+08:002024-10-30T17:12:16+08:00

    Usando gawk:

    Quando $0 é alterado por atribuição ou substituição, $1, $2, etc., e NF serão todos recalculados: da mesma forma, quando um de $1, $2, etc., é alterado, $0 é reconstruído usando OFS para separar campos.

    -- Da Linguagem de Programação AWK

    $ awk '!/HEM/{$0 = gensub(/^((\S+\s+){5})NA(\s.*)/, "\\1Na\\3", "1")}1' file
    

    Ou

    $ awk '!/HEM/ 
      { 
        n=split($0,a, /\s*\S+/, seps); 
        gsub(/NA/, "Na",seps[6]); 
        $0 =""; 
        for(i=1;i<=n;i++) $0 = $0 seps[i-1] a[i] 
     }1'
    

     $ awk -F'[ ]' '!/HEM/
          {
         for(i=1;i<=NF;i++) 
           if ($i ~ /[^[:space:]]+/)
               {
              ++c;
              if (c==6) gsub(/NA/, "Na", $i)
              }   
          c=0
       }1' 
    
    • 1
  3. Best Answer
    Stéphane Chazelas
    2024-10-30T14:28:32+08:002024-10-30T14:28:32+08:00

    Com perlem vez de awk:

    $ cat file
    7353  NA       5.4433   24.4404   -3.0784 NA    456  HEM
    7353  NA       5.4433   24.4404   -3.0784 ANANAN    456  MEH
    $ perl -pe 's{^\s*(\S+\s+){5}\K\S+}{$& =~ s/NA/Na/gr}e unless /HEM/' file
    7353  NA       5.4433   24.4404   -3.0784 NA    456  HEM
    7353  NA       5.4433   24.4404   -3.0784 ANaNaN    456  MEH
    

    ^\s*(\S+\s+){5}\K\S+corresponde sao ritmo branco opcional no início, seguido por 5ocorrências de ritmo não branco S+ ritmo branco s, seguido por não espaço em branco (o 6º campo ), que mantemos Kcomo a correspondência.

    $& =~ s/NA/Na/gré eavaliado como código perl onde o resultado da ssubstituição ( glocalmente como com seu gsub()) de NAwith Nano que foi correspondido ( $&) é rretornado como a substituição do externo s{regex}{replacement}e.

    Se você não pretendia substituir todas as ocorrências de NA dentro do 6º campo , mas apenas substituí-lo por Naif it was NA, então isso pode ser simplificado para:

    perl -ne 's/\s*(\S+\s+){5}\KNA(?!\S)/Na/ unless /HEM/' file
    

    Observe o (?!\S)operador negativo de antecipação, que verifica se NAnão é seguido por um espaço em branco, sem o qual ele também seria substituído NAPOLEONpor NaPOLEON, por exemplo.

    Até sedfaria isso mais facilmente do que awklá:

    s='[[:space:]]' S='[^[:space:]]'
    sed -E "/HEM/! s/^($s*($S+$s+){5})NA($s|\$)/\1Na\3/" file
    

    Com GNU sedou compatível, você pode usar \s/ \Scomo em Perl no lugar de [[:space:]]/ [^[:space:]]. GNU sed(e alguns outros, embora às vezes com uma interface incompatível) também suporta edição -iem in lugares à la perl.

    -Eagora é padrão e suportado pela maioria seddas implementações. Se você estiver em um sistema muito antigo que não o suporta, você pode alterá-lo para:

    s='[[:space:]]' S='[^[:space:]]'
    sed "/HEM/! s/^\($s*\($S\{1,\}$s\{1,\}\)\{5\}\)NA\($s.*\)\{0,1\}\$/\1Na\3/"
    

    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.

      7353  NA       5.4433   24.4404   -3.0784   NA    456   HEM
    

    Por exemplo, seria dividido em 17 "campos":

    1 2   3 4 5      6     7  8      9  10     11 12 13 14 15 16 17
      7353  NA       5.4433   24.4404   -3.0784   NA    456   HEM
    

    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]):

    perl -pe '
      unless (/HEM/) {
        @F = /^\s*|\S+|\s+/g;
        $F[11] =~ s/NA/Na/g; # or $F[11] = "Na" if $F[11] eq "NA"
                             # or $F[11] =~ s/^NA$/Na/
                             # or even $F[11] =~ s/^na$/Na/i
        $_ = "@F";
      }' file
    

    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 no perl -n/-pmodo sed (ou -amodo wk), a menos que você passe a -lopçã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).

    • 0

relate perguntas

  • remova o número de linhas duplicadas com base na correspondência antes da primeira vírgula

  • anexar linhas após outros arquivos linha por linha

  • Como remover uma única linha entre duas linhas

  • Reorganize as letras e compare duas palavras

  • Embaralhamento de arquivo de várias linhas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve