Regex pattern matching using bash

Shell Scripting

 

${var%PATTERN}: Remove the Shortest Match from the End

The variable is expanded, and the shortest string that matches PATTERN is removed from the end of the expanded value. The PATTERN here and in other parameter expansions is a filename expansion (aka file globbing) pattern.
Given the string Toronto and the pattern o*, the shortest matching pattern is the final o:

$ var=Toronto
$ var=${var%o*}
$ printf “%s\n” “$var”
Toront

Because the truncated string has been assigned to var, the shortest string that now matches the pattern is ont:

$ printf “%s\n” “${var%o*}” Tor

This expansion can be used to replace the external command, dirname, which strips the filename portion of a path, leaving the path to the directory (Listing 1). If there is no slash in the string, the current directory is printed if it is the name of an existing file in the current directory; otherwise, a dot is printed.

Listing 1. dname, Print the Directory Portion of a File Path

case $1 in
*/*) printf “%s\n” “${1%/*}” ;;
*) [ -e “$1” ] && printf “%s\n” “$PWD” || echo ‘.’ ;;
esac

${var%%PATTERN}: Remove the Longest Match from the End

The variable is expanded, and the longest string that matches PATTERN from the end of the expanded value is removed:

$ var=Toronto
$ sa “${var%%o*}”
:t:

${var#PATTERN}: Remove the Shortest Match from the Beginning

The variable is expanded, and the shortest string that matches PATTERN is removed from the beginning of the expanded value:

$ var=Toronto
$ sa “${var#*o}”
:ronto:

${var##PATTERN}: Remove the Longest Match from the Beginning

The variable is expanded, and the longest string that matches PATTERN is removed from the beginning of the expanded value. This is often used to extract the name of a script from the $0 parameter, which contains the full path to the script:

scriptname=${0##*/} ## /home/rk/bin/script => script

${var//PATTERN/STRING}: Replace All Instances of PATTERN with STRING

Because the question mark matches any single character, this example hides a password:

$ passwd=zxQ1.=+-a
$ printf “%s\n” “${passwd//?/*}”
*********

With a single slash, only the first matching character is replaced.

$ printf “%s\n” “${passwd/[[:punct:]]/*}” zxQ1*=+-a

${var:OFFSET:LENGTH}: Return a Substring of $var

A substring of $var starting at OFFSET is returned. If LENGTH is specified, that number of characters is substituted; otherwise, the rest of the string is returned. The first character is at offset 0:

$ var=Toronto
$ sa "${var:3:2}"
: on:
$ sa "${var:3}"
: onto:

A negative OFFSET is counted from the end of the string. If a literal minus sign is used (as opposed to one contained in a variable), it must be preceded by a space to prevent it from being interpreted as a default expansion:

$ sa "${var: -3}"
:nto:

${!var}: Indirect Reference

If you have one variable containing the name of another, for example x=yes and a=x, bash can use an indirect reference:

$ x=yes
$ a=x
$ sa "${!a}"
:yes:

The same effect can be had using the eval builtin command, which expands its arguments and executes the resulting string as a command:

$ eval "sa \$$a"
:yes:

${var^PATTERN}: Convert to Uppercase

The first character of var is converted to uppercase if it matches PATTERN; with a double caret (^^), it converts all characters matching PATTERN. If PATTERN is omitted, all characters are matched:

$ var=toronto
$ sa "${var^}"
:Toronto:
$ sa "${var^[n-z]}"
:Toronto:
$ sa "${var^^[a-m]}" ## matches all characters from a to m inclusive
:toronto:
$ sa "${var^^[n-q]}"
:tOrONtO:
$ sa "${var^^}"
:TORONTO:

 

${var,PATTERN}: Convert to Lowercase

This expansion works in the same way as the previous one, except that it converts uppercase to lowercase:

$ var=TORONTO
$ sa "${var,,}"
:toronto:
$ sa "${var,,[N-Q]}"
:ToRonTo:

In case of any ┬ęCopyright or missing credits issue please check CopyRights page for faster resolutions.

Leave a Reply