Note that there are some explanatory texts on larger screens.

plurals
  1. POpattern-matching a comma delimited digits as string
    primarykey
    data
    text
    <p>How do I do a pattern-match for this: 4,7,9....n - a comma delimited string of digits as user input? I'm using case statement for that and I believe, case rather use pattern-matching than regex. This is what user gets:</p> <pre><code>Do you want to delete any of these? [ 1 ] launch-EOsgR4 [ 2 ] launch-SWZQdJ [ 3 ] launch-tHAdIm [ 4 ] launchd-235.z4KTVx [ 5 ] launchd-257.nM2wOZ [ 6 ] progress.log [ 7 ] ssh-8pISGGnlZ5 ---------------------------------------- Single: 4; Multiple: 2,3; Range: 4..7 a to delete all; n to cancel and exit ---------------------------------------- ( [1][2][3][4][5][6][7] | a | n ): </code></pre> <p>And, as the showed above, users got the option for a single number (easy), a range: 6..9 (also not so hard) or multiple: 3,5,6 (find a bit hard with 'single number' option). This is what I've done so far....</p> <pre><code>#!/usr/bin/env bash NL=$(echo -e "\033[0;0m") BD=$(echo -e "\033[0;1m") ERR=$(printf "\n%-25s" "$(echo -e "\033[1;31m[ ERROR ]\033[0m")") WRN=$(printf "\n%-25s" "$(echo -e "\033[1;33m[ WARN ]\033[0m")") ls /tmp | tail -n9 &gt; list_of_file s=$(printf "%-40s" "-") function lstFile() { local file=$1 if [[ -s $file ]] then LINES=( $(cat $file) ); echo "" for ix in ${!LINES[@]} do printf "%-5s%-14s%s\n" "" "${BD}[ $(( ix+1 )) ]" "${LINES[$ix]}${NL}" done else exit 0 fi LST=$(echo ${!LINES[@]}|awk -v ORS=']' '{for (i=1; i&lt;=NF; i++) print "["($i+1)}') } function delOpt() { echo "${s// /-}" echo -e "Single: 4; Multiple: 2,3; Range: 4..7" echo -e "${BD}a${NL} to delete all; ${BD}n${NL} to cancel and exit" echo "${s// /-}" echo -n "( $1 | a | n ): " } echo -e "\nDo you want to delete any of these?" lstFile list_of_file ANS= until [[ "${ANS}" == "N" || "${ANS}" == "n" || "${ANS}" == "e" ]] do delOpt $LST read ANS &amp;&amp; echo "" ANS=$( tr '[:upper:]' '[:lower:]' &lt;&lt;&lt; "$ANS" ) [[ -n $(echo $ANS|grep -E -w "^[aen0-9,]{1,}") ]] &amp;&amp; : || ANS="X" case ${ANS} in [0-9]..[0-9] ) for ix in $(eval echo \{$ANS\}); do LINE=${LINES[(( $ix-1 ))]} echo -e "Deleting: ${BD}${LINE}${NL}" sed -i -c "/$LINE/d" list_of_file done unset LINE lstFile list_of_file ;; [0-9,]* ) ANS=$(echo $ANS | awk -F' |,' '{for (i=1; i&lt;=NF; i++) print $i}') for ix in $ANS; do if [[ $ix -gt ${#LINES[@]} ]] then echo "${ERR}Out-of-range value: ${bd}$ix${NL}" else LINE=${LINES[(( $ix-1 ))]} echo -e "Deleting: ${BD}${LINE}${NL}" sed -i -c "/$LINE/d" list_of_file &gt; /dev/null 2&gt;&amp;1 fi done unset LINE lstFile list_of_file ;; a ) for ix in ${LINES[@]}; do echo "Deleting: ${BD}${ix}${NL}" sed -i -c "/$ix/d" list_of_file done exit 0 ;; n|e ) exit 0 ;; * ) echo "${WRN}Invalid entry! Should be digit or ${BD}a${NL} for All." printf "%-14s%s\n\n" "" "Otherwise, enter ${UL}n${NL}o or ${UL}e${NL}xit to quit" ;; esac done </code></pre> <p>which is working fine (sort of) but there are some race conditions. e.g.</p> <pre><code>2,d,7 - throws in: bad array subscript 6..10 - throws in: (( 6..11-1 )): syntax error: invalid arithmetic operator (error token is "..11-1 ))") but, 6..9 - throws in: first RE may not be empty </code></pre> <p>Is there any way to have separate options to catch 'single' and 'multiple' number input? Also, any suggestions on overall improvement?</p> <p>Any help greatly appreciated. Cheers!!</p> <p><hr> <strong>Update: 31/10</strong><br><br> It's working now. Thanks to Alepac for the suggestion.<br> Just in case, if someone else is also looking for something similar, I'm putting it in here. As per my original code, this function will delete the line(s) from a file: <code>list_of_file</code> according to the user input.</p> <pre><code>function chkINPUT() { local I_PUT=( "$@" ) local MAX=${#LINES[@]} #IFS=', ' read -a SPLITTED &lt;&lt;&lt; "$I_PUT" local SPLITTED=( $(echo "${I_PUT[@]}" | awk -F',| ' '{for (i=1; i&lt;=NF; i++) print $i}') ) for idx in "${!SPLITTED[@]}" do SPLTD=${SPLITTED[idx]} # Check if it's a range [4..7] if [[ "${SPLTD}" =~ ^[0-9]{1,2}\.\.[0-9]{1,2}$ ]] then for ix in $(eval echo \{$SPLTD\}); do if (( ${ix} &lt;= $MAX )); then LINE=${LINES[(( ix-1 ))]} echo -e "Deleting: ${BD}${LINE}${NL}" sed -i -e "/$LINE/d" list_of_file 2&gt;&amp;1 &gt; /dev/null unset LINE else echo -e "\t${ix} =&gt; Out of range" break fi done # Check if it's a single input elif [[ "${SPLTD}" =~ ^[[:digit:]]+$ ]] then if (( ${SPLTD} &lt;= $MAX )); then LINE=${LINES[(( SPLTD-1 ))]} echo -e "Deleting: ${BD}${LINE}${NL}" sed -i -e "/$LINE/d" list_of_file 2&gt;&amp;1 &gt; /dev/null unset LINE else echo "${ERR}Out-of-range value: ${bd}$SPLTD${NL}" fi else echo "${ERR}Invalid entry: ${bd}$SPLTD${NL}; must be an integer from the list!" fi done } </code></pre> <p>and then, use it like this:</p> <pre><code>ANS= until [[ "${ANS}" == "N" || "${ANS}" == "n" || "${ANS}" == "e" ]] do delOpt $LST read ANS &amp;&amp; echo "" ANS=$( tr '[:upper:]' '[:lower:]' &lt;&lt;&lt; "$ANS" ) case ${ANS} in [0-9]* ) chkINPUT ${ANS} ;; </code></pre> <p>Hope it helps. Cheers!!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload