더 나은 보기 메뉴를 얻기 위해 선택 명령을 사용하여 STDERR 형식을 지정할 수 있습니까?
나에게는 간단한 선택이 있다
select oChoice in $(<tempMenu.menu) ; do
case "$oChoice" in
*)
break
;;
esac
done
나는 다음과 같은 트릭을 시도했습니다.
exec 3>&1
select ...
...
done 2>&1 1>&3 | sed 's/^/NICE OUTPUT /'
하지만 다음과 같은 이스케이프 시퀀스(예: 색상)는 사용할 수 없습니다.
...
done 22>&1 1>&3 | sed 's/^/\033[1;33m\033[44mNICE OUTPUT /'
or
done 22>&1 1>&3 | sed 's/^/\\033[1;33m\\033[44mNICE OUTPUT /'
이스케이프 시퀀스는 이스케이프되지 않으며 PS3도 사용자 정의했기 때문에 STDOUT이 변경됩니다.
PS3="$(print \\n\\r)# $(print "\\033[1;33m\\033[44m")"$QUESTION"$(print "\\033[0m\\033[1;1m\\033[44m") `tput sc` $(print "")
#$(print "")
# $(print "")
# Status: $status $(print "")
# $(print "")
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `tput rc` "
내가 이해하는 한도에서는 (화면에 stderr만 표시하고 stdout 및 stderr을 파일에 씁니다.) STDERR을 STDOUT에서 분리할 수 없습니다. 그렇다면 STDOUT만 사용하여 동적 텍스트 기반 메뉴를 만드는 더 스마트한 방법이 있습니까? (또는 내 문제에 대한 다른 해결책)
답변1
오래된 질문을 다시 방문하여적은 노력구현하다. 실제로 두 가지 질문이 하나로 통합되었습니다.
a) STDERR
명령 select
에서 처리됨
select
b) 명령에 표시되는 항목의 모양 변경
select
이 명령을 사용하지 않는 대안이 마련되었습니다 . 그래서 나는 그 길로 가지 않을 것입니다.
이 select
명령은 옵션의 열 레이아웃을 자동으로 처리하므로 매우 편리합니다. 기본적으로 대소문자 처리만 하면 됩니다. 그래서 조금보다는바퀴를 재발명하다이는 여러 가지 간단한 상황에 대한 훌륭한 솔루션이 될 수 있습니다.
가) 처리STDERR
원래 질문 STDERR
에 대한 해결책이 이미 있습니다 STDOUT
.
select choice in ...; do
...
done 2>&1
두 파일 핸들 모두 동일한 기능을 제공하므로 이를 조작할 이유가 없습니다. STDERR
for를 사용하면 select
콘텐츠가 손상되지 않고 STDOUT
리디렉션과 같은 다른 목적으로 사용할 수 있으므로 실제로 좋은 생각입니다.
select
b) 명령에 표시되는 항목의 모양 변경
해결책은개선하다다음 구문을 채택하면 여기의 출력도 매우 간단합니다.
select choice in $(...); do
...
done
$(...)
어떤 작업을 수행하는 데 사용됩니다.화장품의 select items
.
예를 들어, ANSI 터미널에서 색상을 지정할 수 있습니다.
$(for i in *; do print "\[E31m$i\E[0m"; done)
또는 셰이딩 함수를 호출합니다(다른 상황에서 재사용 가능).
function colourise_diritems {
typeset dir=$1 item
for item in $dir/*; do
if [[ -d $item ]]; then print "\E[31m$i\E[0m"
elif [[ -f $item ]]; then print "\E[32m$item\E[0m"
...
fi
done
}
select choice in $(colourise_diritems $PWD); do
...
done
분명히 프로젝트에 태그를 추가하는 경우 위의 예에서 사용하기 전에 결과를 정리해야 합니다 choice
.
choice=${choice#\E[+([^m]*)m}
choice=${choice%\E[+([^m]*)m}
ANSI 시퀀스를 제거합니다.
노트: ANSI 시퀀스로 작업하는 것은 까다로울 수 있으며 추가 테스트가 필요합니다.
답변2
또 다른 접근 방식은 선택을 피하고 메뉴를 만드는 것입니다. 각 메뉴 옵션(action1.sh, xxx.sh 및 Passwords.sh)에 대한 쉘 스크립트를 만들고 menu.cfg에서 구성합니다.
1 action1 Do action 1
2 xxx Another nice item for you
3 passwords Very dangerous
menu.cfg를 읽는 스크립트를 사용하여 메뉴를 실행합니다.
#!/bin/ksh
formatmenu()
{
if [ $# -eq 2 ]
then
printf "%d) %s\n" ${1} "$2"
else
printf " %s\n" "${1}"
fi
}
showMenu()
{
echo "Enter 0 to stop or choose beneath."
cat menu.cfg|while read option proces description
do
formatmenu ${option} ${proces}
formatmenu "${description}"
done
}
getAction()
{
showMenu
while [ ${CHOICE} -eq -1 ]
do
read CHOICE?"Please enter a digit: "
if [[ ${CHOICE} != +([0-9]) ]]
then
CHOICE=-1
echo "Invalid, please enter a digit."
fi
done
}
performAction()
{
if [ ${CHOICE} -eq 0 ]
then
return
fi
process=$(grep "^${CHOICE} " menu.cfg | cut -d\ -f2)
echo "===${process}.sh==="
. ${process}.sh
}
# Start
export CHOICE=-1
getAction
echo choice=${CHOICE}
performAction
exit 0