Teste de RegExp com shell ash (BusyBox)

5

Eu preciso fazer um teste de padrão RegExp em um determinado bit de entrada do usuário. Este é o padrão que preciso para testar o valor.

^([a-z]{2,3})\-([a-z][a-z]*[0-9]*)\-(\d+)$

Um exemplo de correspondência seria: na-examplename-01

O shell que eu tenho disponível é BusyBox a.k.a ash, então eu não tenho funcionalidade bash completa.

Quais são as minhas opções para testes de padrão RegExp ao usar o BusyBox?

Observação: não consigo usar o expr, pois ele não está disponível na minha instalação.

Eu tenho as seguintes funções disponíveis:

arp, ash, awk, basename, bash, bunzip2, bzcat, bzip2, cat, chmod,
chown, chvt, clear, cp, crond, crontab, cryptpw, cut, date, dd,
deallocvt, df, dirname, dmesg, dnsdomainname, dos2unix, du, egrep,
eject, env, fbset, fgconsole, fgrep, find, findfs, flock, free, fstrim,
ftpget, ftpput, fuser, getopt, grep, groups, gunzip, gzip, head,
hostname, httpd, hwclock, id, ifconfig, ifdown, ifplugd, ifup, install,
ionice, iostat, ip, kill, killall, killall5, less, ln, loadkmap,
logger, login, ls, lsof, md5sum, mkdir, mkdosfs, mkfifo, mkfs.vfat,
mknod, mkpasswd, mkswap, mktemp, more, mount, mountpoint, mpstat, mv,
nbd-client, nc, netstat, nice, nohup, nslookup, ntpd, od, pgrep, pidof,
ping, ping6, pmap, printenv, ps, pstree, pwd, pwdx, rdate, readlink,
realpath, renice, reset, rm, rmdir, route, sed, seq, setconsole,
setserial, sh, sleep, smemcap, sort, stat, su, switch_root, sync,
sysctl, tail, tar, tee, telnet, time, top, touch, tr, traceroute,
traceroute6, true, ttysize, umount, uname, uniq, unix2dos, unxz,
uptime, usleep, vconfig, vi, watch, wc, wget, which, whoami, whois,
xargs, xz, xzcat, zcat
    
por James White 18.05.2015 / 13:22

3 respostas

7

Você tem três ferramentas que podem fazer expressões regulares. Todos assumem que $in contém na-examplename-01 .

  1. grep

    $ printf "%s\n" "$in" | ./grep -E '^[a-z]{2,3}-[a-z]+[0-9]*-[0-9]+$'
    na-examplename-01
    
  2. sed

    $ printf "%s\n" "$in" | ./sed -n '/^[a-z]\{2,3\}-[a-z]\+[0-9]*-[0-9]\+$/p'
    na-examplename-01
    
  3. awk

    $ printf "%s\n" "$in" | ./awk '/^[a-z]{2,3}-[a-z]+[0-9]*-[0-9]+$/'
    na-examplename-01
    

Observe que eles correspondem a cada linha dentro de $in em oposição ao conteúdo de $in como um todo. Por exemplo, eles corresponderiam na segunda e terceira linha de um $in definido como

in='whatever
xx-a-1
yy-b-2'

Como Stéphane apontou em sua resposta, é uma boa idéia prefixar esses comandos com LC_ALL=C para garantir que sua localidade não confunda os intervalos de caracteres.

    
por 18.05.2015 / 13:40
5

awk parece um bom candidato:

input='whatever
even spaces
and newlines
xxx-blah12-0' # should not match

input='na-examplename-01' # should match

if
  LC_ALL=C awk '
    BEGIN{
      exit(!(ARGV[1] ~ /^[a-z]{2,3}-[a-z]+[0-9]*-[0-9]+$/))
    }' "$input"
then
  echo it matches
else
  echo >&2 it does not match
fi
    
por 18.05.2015 / 13:35
4

Você pode usar grep no modo regex estendido da seguinte forma:

echo na-examplename-01 | grep -E '^[a-z]{2,3}-[a-z]+[0-9]*-[0-9]+$'

Você deve usar o parâmetro interval para tornar isso mais fácil de ler. [a-z][a-z]|[a-z][a-z][a-z] seria [a-z]{2,3} .

[a-z]+ é o mesmo que [a-z][a-z]*

Para o snytax do grep, dê uma olhada no link

    
por 18.05.2015 / 13:28