bash의 $PS4 - GNU 문서에 언급된 "간접 수준" 동작을 재현하는 방법은 무엇입니까?

bash의 $PS4 - GNU 문서에 언급된 "간접 수준" 동작을 재현하는 방법은 무엇입니까?

내가 읽고있다GNU 문서, 나는 다음 문장이 정의의 일부라고 생각합니다 PS4.

확장된 값의 첫 번째 문자는 여러 수준의 간접 참조를 나타내기 위해 필요한 만큼 복사됩니다. 기본값은 "+"입니다.

+나는 이것을 내 코드의 각 추상화 수준에 대한 기호를 보게 될 것이라는 의미로 해석합니다 . 나는 이 동작을 내 셸에서 재현하고 싶었기 때문에 다음 코드를 작성했습니다.

#!/usr/bin/env bash

function baz() {
  echo "inside baz"
}

function foo() {
  echo "inside foo";
  baz;
}

function bar() {
  echo "inside bar";
  foo;
}

set -x;

bar;

bar나는 호출 foofoo호출 로 인해 최대 3가지 수준의 간접 참조를 가질 것으로 예상하므로 baz다음과 같은(또는 유사한) 출력이 표시될 것으로 예상합니다.

+ bar
+ echo 'inside bar'
inside bar
++ foo
++ echo 'inside foo'
inside foo
+++ baz
+++ echo 'inside baz'
inside baz

그러나 내가 본 것은 그렇지 않았습니다. 대신 나는 다음을 본다:

+ bar
+ echo 'inside bar'
inside bar
+ foo
+ echo 'inside foo'
inside foo
+ baz
+ echo 'inside baz'
inside baz

이 맥락에서 "간접 수준"이 무엇을 의미하는지 오해하고 있는 걸까요, 아니면 해당 수준의 간접 수준을 올바르게 재현하지 못하는 걸까요?

답변1

현재 승인된 답변에서 알 수 있듯이 수준은 평가 및 조달을 통해 증가된 중첩 수준과 관련이 있습니다. 명령 대체를 통해 늘릴 수도 있습니다.

PS4='+ '
echo hello > world
set -x
wc -l $(ls -tc | head -1)

주어진

++ ls -tc
++ head -1
+ wc -l world
1 world

함수 깊이에 관심이 있다면 배열을 사용할 수 있습니다 FUNCNAME. 예를 들어

PS4='+ ${_plus:0:${#FUNCNAME[@]}}${FUNCNAME[0]} '
_plus='================='
bar

작동 방식은 다음과 같습니다. ${#FUNCNAME[@]} 배열의 요소 수로 확장됩니다 FUNCNAME. 현재 호출되는 각 함수에는 배열의 요소가 있으므로 이것이 함수 깊이입니다. 그런 다음 이 값은 첫 번째 N 문자를 선택 $_plus하고 일련의 기호로 설정하는 데 사용됩니다 =. 문자 수는 $_plus절충안입니다. 함수 중첩을 표시하기에 충분한 콘텐츠가 필요하지만 중첩이 깊은 경우(재귀 함수가 있을 수 있음) 프롬프트가 어리석게 길어지는 것도 피하고 싶을 것입니다. 현재 표시 기능이 추가되었습니다 ${FUNCNAME[0]}. $FUNCNAME배열의 최상위 요소만 참조하는 것도 가능 하지만 항상 배열을 배열로, 스칼라를 스칼라로 액세스하면 더 명확해집니다.

OP의 정의에 따르면 이는 다음과 같습니다 foo.barbaz

$ bar
+  bar
+ =bar echo 'inside bar'
inside bar
+ =bar foo
+ ==foo echo 'inside foo'
inside foo
+ ==foo baz
+ ===baz echo 'inside baz'
inside baz

따라서 +줄의 시작 부분은 eval/source/command 대체 중첩 수준을 나타내고, 등호는 함수 중첩 수준을 나타내며, 그 다음에는 현재 속해 있는 함수 이름을 알 수 있습니다.

PS4 프롬프트에 추가하는 것도 고려해야 할 사항 입니다 LINENO.BASH_SOURCE

답변2

간접 주소 지정은 관찰한 기능과 관련이 없으며 eval다음 예에서 볼 수 있듯이 입니다.

#!/usr/bin/env bash
set -x
echo 1
eval "echo 2"
eval 'eval "echo 3"'

이것은 다음과 같은 것을 방출해야합니다

+ echo 1
1
+ eval 'echo 2'
++ echo 2
2
+ eval 'eval "echo 3"'
++ eval 'echo 3'
+++ echo 3
3

그리고 muru가 지적했듯이 소스 파일도 제공됩니다.

$ cat code
echo help
source code
$ bash -x code

control+ 가 c준비되어 준비가 되었기를 바랍니다 ...

관련 정보