This is a new method I made, a function created entirely with Perl Compatible Regular Expressions v. 2:
reinstall-readonlyx () { sudo apt-get update -y sudo apt-get purge -y libconst-fast-perl libreadonly-tiny-perl libreadonly-perl libreadonlyx-perl && sudo apt-get install -y libreadonlyx-perl return $? } reinstall-readonlyx pcre2 () { local readonlyx='' local p='p' local s='--' readonlyx='use ReadonlyX; Readonly::Array ' if [[ $1 = -i && $2 = -n ]]; then set -- "$2" "$1" "${@:3}"; fi if [[ $1 = -n ]]; then p='n' set -- "${@:2}" fi if [[ $1 = -i ]]; then s="$1 $s" set -- "${@:2}" fi perl -0777s${p}E "${readonlyx}"'my @ARGS; BEGIN{@ARGS = @ARGV} END{foreach(@ARGS){if($_ ne "-" && ! -f $_){exit 2}}} '"$1" "$s" "${@:2}" return $? }
In the created function, @ARGS is an array reserved for checking the existence of the files that were passed as arguments. Using the ReadonlyX library, thus making the array read-only, prevents the end user from altering the array during the function call, which would otherwise lose the functionality of returning an error code in case of non-existent files.
Comment out the line like this: #readonlyx='use ReadonlyX; Readonly::Array ' if you don't want to use ReadonlyX anyway.
pcre2-cut () { local function_name="${FUNCNAME[0]}" local i=0 local int='^[+-]*[0-9]+$' local start=1 local num=-1 local delims='\h' local max=false local count=false local expr='[^$d\v]+(?:[$d]+|$)(?=[^$d\v]|$)' local options='say' local param='' local newline='' for (( i=1; i<=$#; i++ )); do param="${!i}" case $param in -- | -s | -n | -d | -m | -c) set -- "${@:1:i-1}" "${@:i+1}" case $param in -s | -n) if [[ ! ${!i} =~ $int ]]; then echo "$function_name: Invalid argument for $param." >&2 return 1 fi ;; esac case $param in --) break;; -s) start="${!i}";; -n) num="${!i}";; -d) delims="${!i}";; -m) max=true;; -c) count=true;; esac case $param in -s | -n | -d) set -- "${@:1:i-1}" "${@:i+1}";; esac ((i--)) ;; esac done ((start+=0)) ((num+=0)) if [[ $start -gt 0 ]]; then ((start--)) else ((start+="$(pcre2-cut -d "$delims" -m -- "$@")")) if [[ $start -lt 0 ]]; then start=0; fi fi if $max || $count; then options='my @c = (); do{push(@c, 0+(() = /'"$expr"'/gm))} for split(/\v/, $_, -1)' if $max; then options="${options}"'; use List::Util qw(max); say max @c' newline='; say ""' fi if $count; then options="${options}${newline}"'; say join("\n", @c)' fi fi pcre2 's/\V\K\z/\n/' -- "$@" | pcre2 's/\v\z//' -- - | if [[ $num -lt 0 ]]; then pcre2 -n 's/^[$d]*((?:'"${expr}"'){$s})?(?(1)(.*?)|.*?)[$d]*$/$2/gm; '"$options" -s="${start}" -d="${delims}" -- - else pcre2 -n 's/^[$d]*((?:'"${expr}"'){$s})?(?(1)((?:[$d]*[^$d\v]+(?=[$d]|$)){$n})?(?(2).*?|(.*?))|.*?)[$d]*$/$2$3/gm; '"$options" -s="${start}" -n="${num}" -d="${delims}" -- - fi return $? }
Usage:
pcre2-cut -s <starting column> -n <number of columns> -d <delimiter(s)>
This function only works with data passed via standard input.
1° parameter: Only integers strictly greater than 0 are allowed for the starting column; if the starting column exceeds the number of columns present, no columns will be taken.
2° parameter: If the number of columns is less than 0, all columns starting from the starting column will be taken; if the number of columns is equal to 0, no columns will be taken; if the number of columns is greater than 0, columns from the starting column will be taken, plus the indicated number of columns. If omitted, the default number of columns is -1.
3° parameter: One or more delimiters are allowed, including all escape characters allowed by Perl regular expressions. This is a very powerful parameter.
If omitted, the default delimiter is \h.
\v Matches unicode vertical whitespace, considered a character class by the PCRE engine:
[\x{2028}\n\r\x{000B}\f\x{2029}\x{0085}]
\h Matches spaces, tabs, non-breaking/mathematical/ideographic spaces, and so on. Works with Unicode. Equivalent to:
[ \t\x{00A0}\x{1680}\x{180E}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005}\x{2006}\x{2007}\x{2008}\x{2009}\x{200A}\x{202F}\x{205F}\x{3000}]
The second and third parameters are interchangeable if the second parameter is not an integer (positive or negative) and thanks to this feature, it is also possible to indicate only the third parameter (the delimiter) omitting the second one.
When obtaining columns, all consecutive delimiter characters will be skipped (unlike the cut command), and delimiter characters (even if consecutive) at the beginning and end of a line will be truncated, regardless of the parameters entered.
grep | awkis an antipattern -- you wantawk '/!/ { print $2 }'svn status | grep '\!' | cut -d' ' -f2- > removedProjs