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 / 707327
Accepted
DEKKER
DEKKER
Asked: 2022-06-25 00:36:34 +0800 CST2022-06-25 00:36:34 +0800 CST 2022-06-25 00:36:34 +0800 CST

Encontrando o número da linha da primeira ocorrência de um texto no script bash

  • 772

Preciso descobrir qual é o número da linha da primeira ocorrência de uma determinada string de pesquisa que deve estar no início de uma linha em um arquivo de texto e armazená-la em uma variável no meu script bash. Por exemplo, quero encontrar a primeira ocorrência de "c":

abc
bde
cddefefef // this is the line that I need its line number
Casdasd // C here is capital, I dont need it
azczxczxc
b223r23r2fe
Cssdfsdfsdf
dccccdcdcCCDcdccCCC
eCCCCCC

Eu inventei isso, mas como você vê, há grandes problemas

   trimLineNum=$(cat "${varFileLog}" | grep -m1 -n "c")
   echo "c is at line #"${trimLineNum}

A saída será:

c is at line #1:abc

Problemas:

  1. Então, obviamente, corresponde à primeira linha, porque há um "c" na linha.
  2. A saída também incluirá o conteúdo da linha! Eu quero que seja apenas o número da linha

o que devo mudar para corrigir esses problemas?

bash text-processing
  • 5 5 respostas
  • 1159 Views

5 respostas

  • Voted
  1. Philippos
    2022-06-25T01:43:44+08:002022-06-25T01:43:44+08:00

    Com POSIX sed, você suprime a saída normal com a -nopção, então para a linha que começa com c(pattern ^c), imprima o número da linha com =e quit:

    sed -n '/^c/{=;q;}'
    

    Com GNU sed, você pode usar o Qcomando para sair sem saída e simplificar para

    sed '/^c/!d;=;Q'
    
    • 7
  2. lauhub
    2022-06-25T01:04:43+08:002022-06-25T01:04:43+08:00

    Existem várias soluções

    com AWK

    awk '/^c/ { print NR; exit}' "${varFileLog}"
    
    • /^c/: corresponde à linha que começa comc
    • print NR: imprime o número do registro (linha)
    • exit: não continua o processamento

    Como eu gosto awk, esta é a minha solução preferida

    com grep + filtragem

    grep -n '^c' "${varFileLog}" | head -n1 | sed 's/:.*//'
    
    • '^c': corresponde à linha que começa comc
    • head -1: exibe apenas a primeira linha dos resultados do grep
    • sed 's/:.*//': remove qualquer coisa após o:

    sed 's/:.*//'e cut -d: -f1ter o mesmo efeito nesse caso

    sobre desempenho

    Isso pode ser mais lento que a solução de Stephen:

    grep -m1 -n '^c' "${varFileLog}" | cut -d: -f1
    
    • 6
  3. Best Answer
    Stephen Kitt
    2022-06-25T00:43:10+08:002022-06-25T00:43:10+08:00

    Você precisa informar grepsobre sua restrição “isso deve estar no início de uma linha”, ancorando a correspondência no início de uma linha com ^:

    trimLineNum=$(grep -m1 -n -- '^c' "${varFileLog}")
    

    Em seguida, a saída do pós-processamento greppara manter apenas o número da linha:

    trimLineNum=$(grep -m1 -n -- '^c' "${varFileLog}")
    trimLineNum="${trimLineNum%%:*}"
    

    Observe que -mé uma extensão GNU (e com GNU grep, você precisa, --mesmo que ^cnão comece com --, caso o $varFileLogpróprio -GNU grepaceite opções mesmo após argumentos não opcionais). Normalmente, você pode canalizar a saída para head -n 1.

    Se não houver correspondência, o primeiro comando retornará false/failure, enquanto o segundo sempre retornará true, a menos que você ative a pipefailopção como suportada por vários shells, incluindo bash.

    • 4
  4. Jessica
    2022-06-25T14:51:02+08:002022-06-25T14:51:02+08:00

    grep pode imprimir o número da linha de uma correspondência com -nou --line-numberentão você pode usar isso.

    $ cat sample.txt | grep '^c' --line-number
    3:cddefefef // this is the line that I need its line number
    10:cat // added to illustrate getting the first occurence vs. all
    

    O problema então se reduz a:

    • Obter apenas a primeira linha
    • Retire apenas o número sem o texto correspondente

    Você pode fazer o primeiro com heade o segundo com cut:

    $ cat sample.txt | grep '^c' --line-number | head -n 1 | cut -d':' -f1
    3
    

    Em sua saída de exemplo, você tem algum texto extra - não tenho certeza se isso é importante para você ou não. No entanto, quando você tem um número em STDOUT, adicionar algum prefixo de string a isso é uma tarefa simples, e deixarei isso para você.

    • 0
  5. jubilatious1
    2022-06-28T06:59:57+08:002022-06-28T06:59:57+08:00

    Usando Raku (anteriormente conhecido como Perl_6)

    raku -ne 'state $i; ++$i; say "c starts line $i" and last if m/^c/;'  
    

    OU

    raku -ne 'state $i; ++$i; say "c starts line $i" and last if (.index("c").defined && .index("c") == 0);' 
    

    OU

    raku -ne 'state $i; ++$i; say "c starts line $i" and last if .starts-with("c");' 
    

    Saídas:

    c starts line 3
    

    -neOs sinalizadores de linha de comando do Raku (sem impressão automática em linhas) são usados. Para obter o número da linha, uma statevariável $ié inicializada uma vez e depois incrementada para cada linha lida. Onde um "c" de início de linha é identificado (por regex, ou index, ou starts-with), a string "c starts line $i"é interpolada e saída ( say).

    Nota: a condicional de baixa precedência as lasté adicionada a cada exemplo acima. Remova essa condicional para retornar todos os números de linha correspondentes, por exemplo:

    ~$ raku -ne 'state $i; ++$i; say "c starts line $i" if m/^c/;'  file
    c starts line 3
    c starts line 10
    

    Adendo: Graças a esta resposta SO , aqui está uma maneira rápida de obter o primeiro número de linha indexado a zero começando com "c" usando a firstrotina do Raku:

    ~$ raku -e 'say lines.first(* ~~ / ^ c /):k;' file
    2
    
    #OR
    
    ~$ perl6 -e 'say lines.first(*.starts-with("c")):k;'  file
    2
    

    Entrada de amostra:

    abc
    bde
    cddefefef // this is the line that I need its line number
    Casdasd // C here is capital, I dont need it
    azczxczxc
    b223r23r2fe
    Cssdfsdfsdf
    dccccdcdcCCDcdccCCC
    eCCCCCC
    cddefefef // this is the line that I need its line number (again)
    

    https://raku.org

    • 0

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

  • como posso alterar o caso do caractere (de baixo para cima e vice-versa)? ao mesmo tempo [duplicado]

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