STDERR KSH를 사용하여 텍스트 기반 메뉴 디자인

STDERR KSH를 사용하여 텍스트 기반 메뉴 디자인

더 나은 보기 메뉴를 얻기 위해 선택 명령을 사용하여 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에서 처리됨

selectb) 명령에 표시되는 항목의 모양 변경

select이 명령을 사용하지 않는 대안이 마련되었습니다 . 그래서 나는 그 길로 가지 않을 것입니다.

select명령은 옵션의 열 레이아웃을 자동으로 처리하므로 매우 편리합니다. 기본적으로 대소문자 처리만 하면 됩니다. 그래서 조금보다는바퀴를 재발명하다이는 여러 가지 간단한 상황에 대한 훌륭한 솔루션이 될 수 있습니다.

가) 처리STDERR

원래 질문 STDERR에 대한 해결책이 이미 있습니다 STDOUT.

select choice in ...; do
...
done 2>&1

두 파일 핸들 모두 동일한 기능을 제공하므로 이를 조작할 이유가 없습니다. STDERRfor를 사용하면 select콘텐츠가 손상되지 않고 STDOUT리디렉션과 같은 다른 목적으로 사용할 수 있으므로 실제로 좋은 생각입니다.

selectb) 명령에 표시되는 항목의 모양 변경

해결책은개선하다다음 구문을 채택하면 여기의 출력도 매우 간단합니다.

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

관련 정보