5

I need to do a RegExp pattern test on a certain bit of user input. This is the pattern I need to test the value against.

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

An example match would be: na-examplename-01

The shell I have available is BusyBox a.k.a ash, so I don't have full bash functionality.

What are my options for RegExp pattern tests when using BusyBox?

Note: I cannot use expr, as it is not available in my install.

I have the following functions available:

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
  • Do you need to extract those 3 groups or just check that the pattern matches? – Stéphane Chazelas May 18 '15 at 11:30
  • Just that the given input matches the format the RegExp pattern is – James White May 18 '15 at 11:32
  • Yes, but what exactly is that format? Are the parentheses capture groups or are they part of the pattern? It looks like you want to match 2 or 3 lower case letters, followed by a -, then 2 or more lower case letters followed by 0 or more numbers, a - and one or more numbers until the end of the line. Is that what you need? – terdon May 18 '15 at 11:34
  • Sorry. I've added an example of what the pattern would/should match. The hyphens are part of the pattern. Your break down of the pattern is correct. – James White May 18 '15 at 11:36
  • 1
    @James [a-z][a-z]* is the same as [a-z]+ – K1773R May 18 '15 at 12:02
7

You have three tools that can do regular expressions. These all assume that $in contains 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
    

Note that those match on each line inside $in as opposed to the content of $in as a whole. For instance, they would match on the second and third line of a $in defined as

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

As Stéphane pointed out in his answer, it's a good idea to prepend these commands with LC_ALL=C to ensure that your locale does not confuse the character ranges.

  • Just for completeness, he actually has more than three tools than can do things with regexes; you've just given the most applicable ones. (vi, less and more can all handle regexes also.) – Wildcard Dec 2 '16 at 20:51
5

awk sounds like a good candidate:

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
  • Good point about the locale with LC_ALL=C – James White May 18 '15 at 11:44
4

You could use grep in extended regex mode like this:

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

You should use the interval parameter to make this more easy to read. [a-z][a-z]|[a-z][a-z][a-z] would be [a-z]{2,3}.

[a-z]+ is the same as [a-z][a-z]*

For the grep snytax, take a look at https://www.gnu.org/software/findutils/manual/html_node/find_html/grep-regular-expression-syntax.html

  • Thanks for showing me where I can optimise my pattern test. – James White May 18 '15 at 11:46
  • or grep -xE '[a-z]{2,3}-[a-z]+[0-9]*-[0-9]+' – Stéphane Chazelas May 18 '15 at 11:55
  • @StéphaneChazelas good one ;) – K1773R May 18 '15 at 11:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.