쉘 스크립트에서 대화형 함수 정의 실행

쉘 스크립트에서 대화형 함수 정의 실행

zsh 또는 bash를 사용하여 사용자에게 여러 명령을 요청하고 이를 함수로 저장할 수 있는 스크립트를 실행하고 싶지만 스크립트가 계속하기 전에 추가 입력을 기다리지 않기 때문에 직접 입력하지 않으면 eval "function $FNCNAME() {"작동 하지 않는 것으로 나타났습니다. echo "function $FNCNAME() {" | zsh -is. 다음 줄 또는 종료.

사용자 입력을 받아들이는 동안 스크립트 프로세스를 차단하고 사용자가 final(따옴표 없이)로 함수 정의를 끝낼 때만 계속하려면 어떻게 해야 합니까 }?

요구사항은 다음과 같습니다.

  • 쉘 자체의 컨텍스트 인식 자동 완성이 활성화되어 있습니다.
  • 스크립트는 지연된 명령을 즉시 실행해서는 안 되지만, 새 함수의 정의를 호출하거나 인쇄할 수 있어야 합니다.

이 질문은 일반적인 배관 및 상호 작용 문제로 제한됩니다. 나는 다음을 요구하지 않습니다:

  • 어떤 방식으로든 미리 작성된 명령을 스크립트에 제공하려면 어떻게 해야 합니까?
  • "최고의 사용자 경험"을 제공하는 방법 또는 이를 개선하는 방법.
  • 왜 이 문제를 해결하고 다른 일을 하면 안 될까요?

답변1

에서는 zsh다음과 같이 보일 수 있습니다.

make-function() {
  local psvar=$1
  local line= body=
  print -ru2 Please enter the definition of the $psvar function, one line at a time, terminate with an empty line.
  while
    line=
    vared -p '%v> ' line
    [[ -n $line ]]
  do
    body+=$line$'\n'
  done
  functions[$psvar]=$body
}

예를 들면 다음과 같습니다.

$ make-function f
Please enter the definition of the f function, one line at a time, terminate with an empty line.
f> echo test
f> return 42
f>
$ f
test
$ echo $?
42
$ functions f
f () {
        echo test
        return 42
}

다음과 같이 할 수도 있습니다.

vared 'functions[f]'

f줄 편집기에서 함수 본문을 편집합니다. Enter편집기를 떠난 후 평소처럼 함수 본문에 리터럴 줄 바꿈을 입력하려면 Alt+ Enter또는 Esc뒤에 Enter(또는 bash의 readline에서와 같이 Ctrl+ v, Ctrl+ ) 가 필요합니다.j

vared(변수 편집기)는 zsh 라인 편집기(zle)를 호출하여 변수의 내용을 편집하는 내장 함수이며 $functions함수 이름을 해당 본문의 코드 표현에 매핑하는 특수 연관 배열입니다.

에서는 readline을 사용하여 편집하는 where를 사용하여 유사한 작업을 수행 bash할 수 있으며 이름과 본문을 사용하여 함수를 생성할 수 있습니다.IFS= read -rep "$psvar> " line-e$lineeval "$psvar() { $body; }"

답변2

이게 당신이 하고 싶은 일인가요?

$ cat ./tst.sh
#!/usr/bin/env bash

tmp=$(mktemp) || exit 1
trap 'rm -f "$tmp"; exit' EXIT

fncname='foo'

printf 'List commands, terminated with Control-D\n' >&2

{
    printf '%s () {\n' "$fncname"
    while IFS= read -r line; do
        printf '\t%s\n' "$line"
    done
    printf '}\n'
} > "$tmp" &&
. "$tmp"

declare -f "$fncname"

"$fncname"

$ ./tst.sh
List commands, terminated with Control-D
echo 'hello'
date
echo 'world'
        <- I hit Control-D here
foo ()
{
    echo 'hello';
    date;
    echo 'world'
}
hello
Wed Jan  3 15:48:38 CST 2024
world

관련 정보