Converter a string “1-5” em array de números no bash

3

Qual é a melhor abordagem para converter a string contendo o intervalo de números em números? Esse formato é usado, por exemplo, na definição do intervalo de páginas a serem impressas. Eu defino, quero imprimir estas páginas "11-14,17,20" . Agora preciso escrever o script bash que mudará essa string para a matriz de números: 11, 12, 13, 14, 17, 20

Ele deve ser capaz de trabalhar com strings que contenham números (mesmo com mais dígitos) e com ',' e '-'.

    
por srnka 03.11.2011 / 10:37

5 respostas

3

Isso é feito em Perl:

echo 11-14,17,20 | perl -pe 's/(\d+)-(\d+)/join(",",$1..$2)/eg'

Saída:

11,12,13,14,17,20
    
por 03.11.2011 / 12:07
3

Aqui está uma solução usando awk :

#!/bin/bash

pages="11-14,17,20"

echo $pages | awk 'BEGIN { RS=","; FS="-"; ORS="" }
  NR > 1  { print "," }
  NF > 1  { for (i=$1; i<$2; ++i) { print i "," } print $2; next }
          { print $1 }'

Isso resulta na seguinte saída:

11,12,13,14,17,20

    
por 03.11.2011 / 11:55
2

Apenas bash:

expand_ranges() {
  local IFS=,
  set -- $1
  for range; do
    case $range in 
      *-*) for (( i=${range%-*}; i<=${range#*-}; i++ )); do echo $i; done ;;
      *)   echo $range ;;
    esac
  done
}
numbers=( $(expand_ranges 11-14,17,20) )

Para a saída solicitada: IFS=,; echo ${numbers[*]}

    
por 03.11.2011 / 14:53
0

Se você tem jot do seu sistema

Exemplo de uso de jot e sed é (não se esqueça do caracter newline na string de substituição!):

$echo 1-2,3,6-9| sed 's/,/\
/g'|sed -E '/-/s/([0-9]+)-([0-9]+)/-  /g;s/^([0-9]+)$/-  /g'| xargs -L 1 jot | rs -t -C,
1,2,3,6,7,8,9

Se você digitar echo jot em vez de "jot" (e remover rs call), deverá ver a seguinte saída:

jot - 1 2
jot - 3 3
jot - 6 9
    
por 03.11.2011 / 14:19
0

Esta é uma maneira meio lisp de fazer as coisas (exceto pelo fato de que bash não gosta de listas preguiçosas, então nós temos que definir um limite superior no número máximo de páginas; aqui eu escolhi 10000)

pages="11-14,17,20"; for ((i=1;i<10000;i++)); do echo -n $i, ; done | cut -d , -f $pages

Com as páginas, você especifica o intervalo de páginas como na outra postagem. O loop for gera uma lista de números de páginas. Desses, o comando cut seleciona os que você quer.

    
por 18.01.2012 / 14:24