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 / 729279
Accepted
404 Name Not Found
404 Name Not Found
Asked: 2022-12-22 19:29:18 +0800 CST2022-12-22 19:29:18 +0800 CST 2022-12-22 19:29:18 +0800 CST

Regex: Corresponde apenas ao nível de lista mais profundo

  • 772

Eu compilei uma lista de materiais que eu precisava em um jogo, começando de cima para baixo até seus ingredientes mais primitivos. No entanto, agora estou procurando uma maneira de calcular rapidamente os números.

21 reinforced alloy
    21 damascus steel
        21 steel
            21 iron dust
            21 carbon
            21 iron
        21 iron dust
        21 carbon
        21 iron
    21 hardened metal
        21 damascus steel
            21 steel
                21 iron dust
                21 carbon
                21 iron
            21 iron dust
            21 carbon
            21 iron
        21 duralmin
            21 aluminum dust
            21 copper dust
            21 aluminum
                21 aluminum dust
        21 compressed carbon
            84 carbon
        21 aluminum bronze
            21 aluminum dust
            21 bronze
                21 copper dust
                21 tin dust
                21 copper
            21 aluminum
                21 aluminum dust
    21 corinthian bronze
        21 silver dust
        21 gold dust
        21 copper dust
        21 bronze
            21 copper dust
            21 tin dust
            21 copper
    21 solder
        21 lead dust
        21 tin dust
        21 lead
            21 lead dust
    21 billon
        21 silver dust
        21 copper dust
        21 silver
            21 silver dust
    21 gold 24 carat

Os níveis superiores não importam, pois estou procurando as matérias-primas que preciso coletar. Por exemplo, 21 hardened metale 21 damascus steelnão importa, porque estou procurando o total de 42 damascus steel, o que também não importa, porque estou procurando 42 iron dust, 42 carbon, e 42 iron(este exemplo não conta o restante da lista), o contagem total de matérias-primas.

Até agora, fiz isso em um site de teste regex , mas eventualmente gostaria de poder usar greppara não ter que abrir um site para fazer a contagem. Eu gostaria de obter algo como "existem 5 ocorrências de carbono, aqui estão as linhas correspondentes" para que eu possa calcular mais facilmente, pois se eu souber que existem 5 ocorrências de carbono com 4 delas sendo e 1 sendo , 21 carbonagora 84 carbonposso calcular facilmente que eu preciso de um total de 21*4 + 84 = 168 carbon.

Estou tentando contar as linhas que não têm outra linha com uma quantidade maior de guias a seguir, pois presumivelmente, se tiver, não é a matéria-prima.

/(\t+)\d+ aluminum\n(?!\1)/g(substituindo "alumínio" por qualquer contagem de matéria-prima que estou tentando encontrar)

Isso não está encontrando nada embora. Existe uma maneira de conseguir o que estou tentando alcançar com o regex? Em caso afirmativo, como?

Obrigado pelo seu tempo.


Não tenho certeza se devo colocar isso no SO ou neste SE, mas como eventualmente quero poder usar, greppensei que este poderia ser o local mais apropriado.

grep
  • 3 3 respostas
  • 324 Views

3 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2022-12-23T02:54:24+08:002022-12-23T02:54:24+08:00

    Se você quiser usar regexps semelhantes ao perl, por que não usar o real:

    <your-file perl -l -0777 -ne '
      while (m{^(\s*+)(\d+) (.*)$(?!\n\1\s)}mg) {
        $count{$3} += $2
      }
      END {
        printf "%4d %s\n", $count{$_}, $_ for sort keys %count
      }'
    

    Que dá:

      84 aluminum dust
     168 carbon
      42 copper
     105 copper dust
      21 gold 24 carat
      21 gold dust
      84 iron
      84 iron dust
      42 lead dust
      63 silver dust
      63 tin dust
    

    -0777 -nsignifica que toda a entrada é sugada para $_. O msinalizador ultiline para o m{...}operador faz com que ^e $corresponda no início e no final de cada linha $_em vez de apenas no início e no final de $_. Sem o s sinalizador, .não corresponde a um caractere de nova linha, mas cuidado com o \sque pode prejudicar as coisas aqui se houver linhas em branco na entrada.

    \s*+é a versão sem retrocesso do \s*. Não é estritamente necessário aqui, pois o que segue ( \d+) não pode corresponder a um espaço em branco.

    Standard grepnão oferece suporte a regexps semelhantes a perl, como aqueles \de (?!\1)operadores perl RE que você está usando, mas você pode usar pcregrepo que também oferece suporte -oa um modo multilinha com -M:

    <your-file pcregrep -Mo '^(\s*+)\K.*$(?!\n\1\s)'
    

    Você ainda precisaria canalizar para outra coisa como perlou awkfazer as somas, então isso tem pouca vantagem sobre usar perlpara tudo.

    Se o recuo pode ter uma mistura de tabulações e espaços, você pode querer que a entrada passe por um expandou unexpandprimeiro para consolidá-los em apenas espaços ou apenas tabulações. Por padrão, eles consideram as paradas de tabulação com 8 colunas de distância, como a maioria dos terminais ou navegadores (mas não o stackexchange, que irritantemente tem 4 colunas de distância), mas veja a -topção de mudar isso.

    • 5
  2. JJoao
    2022-12-23T03:04:56+08:002022-12-23T03:04:56+08:00

    Uma linha é um "ingrediente primitivo" (primi) se seu nível for <= nível do próximo elemento. Isso é equivalente a:

    A linha anterior é um primi se seu nível for <= nível atual (ou se for o último)

    Usando awk com separador de campo "\t", os níveis são NF, os ingredientes são o último campo $NF:

    awk -F '\t' 'prevlev>=NF  {print primi}; 
                              {prevlev = NF; primi=$NF } 
                 END          {print $NF}'
    

    Para resumi-los, você poderia executar algo ao longo das linhas de

    ... | sed 's/ /\t/' | datamash -g 2 -s sum 1
    
    • 4
  3. xiota
    2022-12-22T20:12:07+08:002022-12-22T20:12:07+08:00

    Você precisa usar lookbehind e lookahead. Você também precisa tratar toda a entrada em conjunto, em vez de linha por linha. O seguinte comando deve fazer o que você deseja:

    grep -Pzo '(?<=\n)(\s+)(\S[^\n]*)(?!\n\1\s)' input_file
    
    • -Pativa a sintaxe Perl.

    • -zusa terminador nulo, em vez de novas linhas.

    • -oemite apenas a correspondência.

    • (?<=\n)olha para trás para uma nova linha. Isso está no lugar de ^, que normalmente corresponderia ao início de cada linha. Para olhar negativo para trás, use (?<!...). Estou ignorando a primeira linha porque presumivelmente sempre haverá um nível mais profundo. Se não for esse o caso, você pode adicionar uma nova linha ao início da entrada antes de enviá-la para grep. Provavelmente existem maneiras melhores de fazer isso, mas aqui está uma:

      ( echo ; cat input_file ) | grep ...
      
    • (\s+)captura o nível de indentação. Isto é referido mais tarde como \1. \scorresponde ao espaço em branco. Um problema potencial com isso é que as novas linhas podem ser consideradas parte do recuo. Por exemplo, novas linhas duplas são freqüentemente usadas como separadores de parágrafo. Você pode substituir \spelo espaço em branco específico que espera ser usado para recuo, [\ \t].

    • (\S[^\n]*)captura o texto de interesse. \Scorresponde a não-espaço em branco. [^\n]corresponde a qualquer coisa que não seja uma nova linha.

    • (?!\n\1\s)olhar negativo para a frente para garantir que a próxima linha não seja recuada mais profundamente do que a linha atual. Para uma visão positiva do futuro, use (?=...).

    • 2

relate perguntas

  • resultados inesperados de `service | grep`

  • Leia o arquivo de texto com palavras e sua contagem de ocorrências e saída de impressão classificada

  • Comando ls | grep mostrando apenas diretórios (quando também deveria mostrar arquivos)

  • quando o grep conta e quando não

  • grep --line-buffered até X 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