문자열을 문자별로 읽고 처리하지만 사용자가 입력에 대해 간단한 줄 편집을 할 수 있도록 허용합니다.

문자열을 문자별로 읽고 처리하지만 사용자가 입력에 대해 간단한 줄 편집을 할 수 있도록 허용합니다.

터미널에서 입력 줄을 점진적으로 읽고 사용자에게 INS, DEL, 오른쪽, 왼쪽, 끝, 백스페이스 기능을 허용하고 싶습니다.

문자열이 수정될 때마다 이를 처리하여 텍스트 파일에 대해 증분 정규식 검색을 수행하고 싶습니다.

이러한 편집 키와 기타 키는 여러 입력 문자를 생성하므로
입력을 해석하기가 매우 어렵습니다. 예를 들어 C-Left는 6개의 문자를 생성합니다.

문자별로 편집 가능한 입력을 쉽게 얻을 수 있는 방법이 있습니까?
나머지 처리는 bash에서 수행되므로 bash에서 이 작업을 수행하는 방법을 알고 싶습니다. 다른 제안도 환영합니다.

그렇게 시작했는데, 잠재적인 제어 코드가 너무 많아서 조금 감당하기 어려웠습니다.

#!/bin/bash
IFS=$'\n' 
while true ;do
  read -n 1 c
  ((${#c}==0)) && break # Exit the loop. Input length is 0  
                        # ie. The user has pressed Enter
  echo "xx=$(echo -n "$c"|xxd -p)="
  # 1b 5b 32 7e  "INS"
  # 1b 5b 33 7e  "DEL"
  # 1b 5b 43     "RIGHT"
  # 1b 5b 44     "LEFT"
  # 1b 5b 46     "END"
  # 1b 5b 48     "HOME"
  # 7f           "BACKSPACE"
done

답변1

한 번에 한 문자씩 읽는 경우 read -n키 시퀀스 파서를 구현해야 합니다. 다음을 사용하여 대부분의 터미널에서 작동하는 느리고 지저분한 솔루션을 구축할 수 있습니다. 이스케이프 문자로 시작하여 임의의 수의 문자로 계속되는 기능 키 이스케이프 시퀀스를 고려한 다음 0-9;[]O이 문자 세트에 없는 마지막 문자가 이어집니다.

입력을 읽는 더 좋은 방법은 적절한 입력 라이브러리를 사용하는 것입니다. Bash는 이를 자체 목적으로 사용합니다(독서선). 내장을 사용하여 bind자신만의 키 바인딩을 선언 하면 bind -x키를 누를 때 쉘 명령을 실행하도록 특별히 설계된 제한된 인터페이스를 얻을 수 있습니다. 제한된 인터페이스로 인해 원하는 것을 구현하는 것이 가능할 수도 있지만 어렵습니다.

Zsh에는 자체 입력 라이브러리가 있습니다.즐러. 인터페이스는 bash보다 훨씬 풍부합니다. zle을 사용하면 임의의 키맵을 정의할 수 있고 쉘 코드에서 zle의 내부 기능에 더 잘 액세스할 수 있습니다. zle사용자 정의 명령(위젯이라고 함)에 쉘 기능을 할당하고, bindkey자신만의 키맵을 생성 및 채우고, 마지막으로 vared선택한 키맵을 사용하여 입력 줄을 읽는 데 사용됩니다 .

답변2

read문자가 있는 경우 첫 번째 터미널 이후에 터미널을 원시 모드로 설정한 esc다음 두 번째 터미널을 사용하여 read나머지 바이트(있는 경우)를 읽고 구문 분석할 수 있습니다(참조).BASH는 캐릭터 트라우마에서 벗어났습니다.또한보십시오화살표.txt).

#!/bin/bash

# tested on Mac OS X 10.6.8

IFS=$'\n'
old_tty_settings="$(stty -g)"
exec 0</dev/tty

tput smir  # enable insert mode

while IFS="" read -r -s -n1 key; do    # first read (reads only a single byte)

#od -c <<<"$key"
#continue

((${#key}==0)) && break

case "$key" in
  $'\001')  printf '\r'                          #  ctrl-a
            continue;;   
  $'\177')  tput rmir 
            printf "\010\040\010\033[P"          # backspace
            tput smir
            continue;;                          
  $'\025')  printf "\033[1K"                     # tput el1 does not work on Mac OS X 10.6.8 
            continue;;                           # ctrl-u  (clear to start of line)
  $'\v')    tput el
            continue;;                           # ctrl-k  (clear to end of line)
esac

# if the first char is esc (i.e. \e or \033 respectively)
if [[ "$key" == $'\033' ]]; then    

  stty cbreak -echo min 0 time 0   # set raw terminal 

  IFS="" read -r bytes     # second read (reads remaining bytes)

  if [[ ${#bytes} -gt 0 ]]; then

     stty "$old_tty_settings"

     case "${key}${bytes}" in 
       $'\033[3~')   tput dch1         # delete one char
                     continue;; 
     esac

     printf "${key}${bytes}"

  else
     stty "$old_tty_settings"
  fi

 else

  #stty "$old_tty_settings"
  printf '%s' "$key"

fi

done

echo

exit 0

답변3

명령줄 도구 살펴보기선택자.

# usage examples
selector -v -x @ <(find . -maxdepth 2 -type d | awk '{print $0"@cd "$0}')
selector -v -x @ <(grep -E -o 'http[^ ]+' fileWithURLS)

답변4

스크립트를 사용하지 않고 bash 내장 기능만 사용하세요:

read -e INPUT  # single line

INPUT=$(</dev/stdin)  # multiple lines

(원천)

또는 ledit패키지를 설치한 후 다음을 사용할 수 있습니다.

INPUT=$(ledit)

관련 정보