고정 접두사가 있는 셸 변수 나열

고정 접두사가 있는 셸 변수 나열

찾아봤는데 답을 못찾아서 혹시 전에 질문하신 분이 계시다면 미리 사과드립니다.

저는 FreeBSD에서 쉘을 사용하고 있습니다( /bin/sh그리고 모든 쉘을 표준 출력으로 덤프하고 싶습니다(아니요_myvar_내가 얻을 수 있는 가장 가까운 것은 이지만 set | grep '^_myvar_'여러 줄 변수의 첫 번째 줄만 덤프하며(일부는 여러 줄이고 전체 변수가 필요함) 다음과 같은 병리학적 극단적인 경우에는 오류가 발생하기 쉬울 수 있습니다 . " 문자열을 포함마와르"이것은 해당 섹션의 줄바꿈 ​​직전에 발생합니다.

(값 대신) 변수 이름만 나열할 수 있다면 a를 필터링하여 do...read...while이름이 일치하는 변수의 값을 한 번에 가져올 수 있지만 이를 수행할 방법을 찾을 수 없습니다. 또한 출력 줄에 연속 또는 새 변수가 포함되어 있는지 알 수 있는 확실한 방법이 없기 때문에 전체 출력을 필터링할 수 없습니다. 이는 _myvar_, 문자 =또는 newline (\n)후행 문자를 포함하는 문자열에 대한 극단적인 문제 공간을 나타내지 않습니다. . 코드가 다른 코드 내에 포함되어 있고 환경이 이에 대해 안정적으로 유지되어야 하기 때문에 환경을 수정하고 싶지 않습니다.

도움이 된다면 출력/목록에 일치하는 환경 변수가 포함되어 있는 것은 문제가 되지 않습니다(존재하는 경우 가능성은 매우 낮습니다).

이를 수행할 수 있는 방법이 있습니까?

답변1

setFreeBSD의 내장 sh출력 형식은 쉘에 다시 입력하는 데 적합하므로 다음을 수행할 수 있습니다 :

out() case $1 in (_myvar_*) printf '%s\n' "${1%%=*}"; esac
eval "$(set | sed 's/^/out /')"

즉, set출력되는 각 행에 를 붙이고 "out "쉘 코드로 평가합니다(여기서 는 out첫 번째 인수의 하위 문자열을 첫 번째 인수에 인쇄하는 함수입니다 =).

sed여러 줄 변수의 내용 도 삽입되지만 함수가 첫 번째 변수 이후에 받는 "out "인수에는 여전히 포함되므로 표시하지 않는 부분에 포함됩니다.out=

예를 들어 set다음 출력의 경우:

TERM=xterm
USER=stephane
_myvar_foo='line1
line2
line3'

우리는 다음을 평가할 것입니다:

out TERM=xterm
out USER=stephane
out _myvar_foo='line1
out line2
out line3'

out하지만 이 3개 변수는 3번만 호출되기 때문에 여전히 문제가 되지 않습니다 .

변수 이름과 값을 인쇄하려면 다음을 수행하십시오.

out() case $1 in (_myvar_*)
  eval 'printf "name: \"%s\" value: \"%s\"\n" "${1%%=*}" "${'"${1%%=*}"'}"'
esac
eval "$(set | sed 's/^/out /')"

출력만 되니 참고하세요변하기 쉬운, 위치 매개변수와 같은 다른 유형의 매개변수 대신 $-...

sh이 방법은 출력 전용 구현 에만 사용할 수 있습니다.set스칼라변수(배열이나 연관배열, 복합변수에는 적용되지 않으며 out var=(x)구문 오류가 됩니다). 다른 변수 유형이 있는 셸은 일반적으로 더 나은 자체 검사 기능을 갖습니다.

존재하다 zsh:

typeset -pm '_myvar_*'

아니면 그냥 이름 때문에

echo $parameters[(I)_myvar_*]

존재하다 bash:

v=("${!_myvar_@}"); ((${#v[@]})) && typeset -p -- "${v[@]}"
echo "${!_myvar_@}"

답변2

더 이상 필요하지 않았기 때문에 @StéphaneChazelas의 솔루션을 다음과 같이 단순화했습니다. 누군가에게 도움이 될 수 있도록 아래에 게시하십시오. 그러나 스테판은 단지 수정된 버전일 뿐인 답을 찾았습니다.

#!/bin/sh

get_vars() {
  if printf '%s' "$1" | grep -qE '^_myvar_'; then
    printf '%s\n' "$1" | sed 's/^get_vars //'
  fi
}

eval "$( set | sed 's/^/get_vars /' )"

eval호출은 각 줄에 접두사를 추가하지만 해당 값이 출력되는 방식 때문에 실제로는 set각 변수에 대한 명령을 생성합니다. get_vars VARNAME=VALUE이를 평가하면 명령이 실행됩니다. 그런 다음 호출할 때마다 get_vars현재 줄에 캡처된 변수가 필수 정규식과 일치하는지 확인하고, 그렇다면 "get_vars "두 번째 및 후속 줄에서 접두사를 제거하고 결과를 표시합니다.

관련 정보