Dado algum número, use grep para encontrar onde o número pertence em uma lista numerada?

0

Eu tenho um número (digamos 13) e quero descobrir onde ele deveria estar em uma lista numerada incompleta. Aqui está uma lista de exemplos:

1
3
4
5
9
16
17
21

Obviamente o 13 iria entre o 9 e o 16, mas como faço para o próximo número mais alto dado que eu tenho o número 13. ie Como eu criaria um grep para 16 dado que eu tenho 13?

A razão pela qual estou perguntando é porque eu quero usar sed ou awk para inserir uma linha com base em um parâmetro de pesquisa, mas não consigo descobrir como encontrar a localização.

Por favor, deixe-me saber se eu preciso esclarecer, pois é um pouco difícil para eu explicar.

    
por Evan 30.04.2015 / 20:17

3 respostas

1

Talvez não seja o que você queria, mas, como você está realmente tentando inserir um valor, eu pessoalmente adicionaria o número à lista e usaria sort -n para colocar as coisas na ordem correta.

Esse comando pode ter esta aparência (se a lista estiver em um arquivo):

echo 13 | cat listfile - | sort -n | sed '/^$/d' | cat - > listfile

(Substitua o 13 pelo número que você deseja inserir, talvez a variável x , para que a sequência de comandos comece com echo $x | )

Para uma explicação, vou dividir:

  • echo 13 | gera o número 13 para stdout, que é então canalizado para o próximo comando
  • cat listfile - | primeiro pega o conteúdo do listfile, depois tudo de stdin até um EOF, e então canaliza o resultado concatenado para o próximo comando 'stdin
  • sort -n | pega a lista de canais e a classifica levando em consideração a natureza numérica da entrada (conforme fornecido pela opção -n, também ver man sort )
  • sed '/^$/d' | remove as linhas vazias da string e as encaminha novamente
  • cat - > listfile coloca a coisa toda de volta no listfile novamente. Sim, isso funciona em oposição a coisas como sed 's/a/b/g somefile > somefile' , o que esvaziaria o arquivo.

Se você quiser dividi-lo em vários comandos, poderá tornar a coisa mais legível, sempre operando no arquivo:

echo 13 >> listfile
sort -n listfile
sed -i '/^$/d' listfile

Isso também pode ser útil se você precisar adicionar várias entradas. Basta anexá-los a todos e, em seguida, ordenar (o que pode ser mais rápido do que procurar posições de inserção a cada vez).

O comando acima também funciona se você estiver operando em variáveis. Para isso, o conteúdo do var deve estar presente como uma string usando separação de nova linha para que possa ser ordenada por linha.

Se os valores forem, por exemplo espaço separado, você poderia usar o seguinte comando

list=$(echo $list 13 | sed -r 's/\s+/\n/g' | sort -n | sed '/^$/d')

Além da atribuição de variável, o único novo comando é o primeiro sed , que substitui qualquer sequência contígua de caracteres de espaço em branco (incluindo novas linhas) por novas linhas para criar separação de linha. Na atribuição de variáveis, a lista será automaticamente convertida de volta para a separação do espaço.

    
por s3lph 30.04.2015 / 21:02
0

AFAIU é quase impossível adivinhar a menos que você saiba o intervalo de números ao lado do número que você conseguiu. Por exemplo, o próximo número poderia ser 14, poderia ser 50, poderia ser 1000. Se você souber o intervalo em que o próximo número estará, poderá fazê-lo facilmente:

$ grep -E -m 1 "1[4-9]|2[0-9]|3[0-9]|4[0-9]" file.txt
16

Aqui estou procurando números maiores que 13 e o intervalo é 14 < = NUM < = 49. -m 1 garante que grep pare depois de encontrar a primeira correspondência, neste caso, o próximo número após 13 em o arquivo.

EDITAR: Se você não tem certeza, pode tentar este script:

#!/bin/bash
i=14
while :; do
    grep "$i" file.txt 2>/dev/null && break || i=$((i+1))
done

Defina i como o número que você obteve mais 1. Ele irá percorrer o arquivo procurando números maiores que 13, se o número for mostrado e a operação terminar, caso contrário, o número será incrementado em um e a pesquisa será continue.

    
por heemayl 30.04.2015 / 20:27
0

Se você quiser usar awk para inserir algo, use-o diretamente:

awk 'flag { print "I am inserting stuff"; flag = 0} $1 > 13 && !seen {flag = 1; seen = 1} 1'

Com o seu exemplo:

$ awk 'flag { print "I am inserting stuff"; flag = 0} $1 > 13 && !seen {flag = 1; seen = 1} 1' foo
1
3
4
5
9
16
I am inserting stuff
17
21
    
por muru 01.05.2015 / 07:18