これに対してパターンマッチを行うにはどうすればよいですか: 4,7,9....n - ユーザー入力としてカンマで区切られた数字の文字列? 私はそのためにケースステートメントを使用しています。ケースではなく、正規表現よりもパターンマッチングを使用していると思います。これはユーザーが得るものです:
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 ):
そして、上に示したように、ユーザーは単一の数字 (簡単)、範囲: 6..9 (それほど難しくない)、または複数: 3,5,6 (「単一の数字」では少し難しい) のオプションを取得しました。オプション)。これは私がこれまでやってきたことです....
#!/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 > 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<=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 && echo ""
ANS=$( tr '[:upper:]' '[:lower:]' <<< "$ANS" )
[[ -n $(echo $ANS|grep -E -w "^[aen0-9,]{1,}") ]] && : || 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<=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 > /dev/null 2>&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
これは(ある程度)正常に動作していますが、競合状態がいくつかあります。例えば
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
「単一」と「複数」の数値入力をキャッチするための個別のオプションを持つ方法はありますか? また、全体的な改善に関する提案はありますか?
どんな助けでも大歓迎です。乾杯!!
更新: 31/10
現在動作しています。提案をしてくれた Alepac に感謝します。
念のため、他の誰かが同様のものを探している場合は、ここに入れます. 私の元のコードによると、この関数はファイルから行を削除します:
list_of_file
ユーザー入力に従って。
function chkINPUT()
{
local I_PUT=( "$@" )
local MAX=${#LINES[@]}
#IFS=', ' read -a SPLITTED <<< "$I_PUT"
local SPLITTED=( $(echo "${I_PUT[@]}" | awk -F',| ' '{for (i=1; i<=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} <= $MAX )); then
LINE=${LINES[(( ix-1 ))]}
echo -e "Deleting: ${BD}${LINE}${NL}"
sed -i -e "/$LINE/d" list_of_file 2>&1 > /dev/null
unset LINE
else
echo -e "\t${ix} => Out of range"
break
fi
done
# Check if it's a single input
elif [[ "${SPLTD}" =~ ^[[:digit:]]+$ ]]
then
if (( ${SPLTD} <= $MAX )); then
LINE=${LINES[(( SPLTD-1 ))]}
echo -e "Deleting: ${BD}${LINE}${NL}"
sed -i -e "/$LINE/d" list_of_file 2>&1 > /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
}
そして、次のように使用します。
ANS=
until [[ "${ANS}" == "N" || "${ANS}" == "n" || "${ANS}" == "e" ]]
do
delOpt $LST
read ANS && echo ""
ANS=$( tr '[:upper:]' '[:lower:]' <<< "$ANS" )
case ${ANS} in
[0-9]* )
chkINPUT ${ANS}
;;
それが役に立てば幸い。乾杯!!