$ {var} 매개 변수 확장 표현식이 bash에 중첩 될 수 있습니까?
내가 가진 것은 다음과 같습니다.
progname=${0%.*}
progname=${progname##*/}
이것은 한 줄, 즉 단일 표현식으로 중첩 (또는 중첩되지 않음) 할 수 있습니까?
기본 이름 만 남도록 스크립트 이름에서 경로와 확장명을 제거하려고합니다. 위의 두 줄은 잘 작동합니다. 내 'C'성격은 단순히 나를 더 난독하게 만들도록 유도합니다.
둥지에 의해 다음과 같은 것을 의미합니다.
#!/bin/bash
export HELLO="HELLO"
export HELLOWORLD="Hello, world!"
echo ${${HELLO}WORLD}
그러면 ${var}
식을 중첩 할 수 없습니다 . bash 구문 확장기는 이해하지 못합니다.
그러나 문제를 올바르게 이해하면 basename
명령 을 사용하여 볼 수 있습니다 . 주어진 파일 이름에서 경로를 제거하고 확장자가 주어지면 해당 명령도 제거합니다. 예를 들어 실행 basename /some/path/to/script.sh .sh
하면 script
.
Bash는 간접 확장을 지원합니다.
$ FOO_BAR="foobar"
$ foo=FOO
$ foobar=${foo}_BAR
$ echo ${foobar}
FOO_BAR
$ echo ${!foobar}
foobar
이것은 당신이 찾고있는 중첩을 지원해야합니다.
다음 옵션이 저에게 효과적이었습니다.
NAME="par1-par2-par3"
echo $(TMP=${NAME%-*};echo ${TMP##*-})
출력은 다음과 같습니다.
par2
오래된 스레드이지만 아마도 대답은 Indirection : $ {! PARAMETER}의 사용입니다.
예를 들어, 다음 행을 고려하십시오.
H="abc"
PARAM="H"
echo ${!PARAM} #gives abc
이 중첩은 bash에서는 가능하지 않지만 zsh에서는 작동합니다.
progname=${${0%.*}##*/}
실제로 두 단계를 사용하여 bash에서 중첩 된 변수를 생성 할 수 있습니다.
다음은 user1956358이 제안한 아이디어를 사용하여 Tim의 게시물을 기반으로 한 테스트 스크립트입니다.
#!/bin/bash
export HELLO="HELLO"
export HELLOWORLD="Hello, world!"
# This command does not work properly in bash
echo ${${HELLO}WORLD}
# However, a two-step process does work
export TEMP=${HELLO}WORLD
echo ${!TEMP}
출력은 다음과 같습니다.
Hello, world!
명령 줄에서 ' info bash '를 실행 한 다음 ' Shell Parameter Expansion ' 을 검색하여 설명하는 깔끔한 트릭이 많이 있습니다 . 나는 오늘 몇 권을 읽고 있었는데, 하루 중 20 분 정도를 잃어 버렸지 만, 내 대본은 훨씬 나아질 것입니다 ...
업데이트 : 더 많은 것을 읽은 후 초기 질문에 따라이 대안을 제안합니다.
progname=${0##*/}
그것은 반환
bash
같은 표현은 ${${a}}
작동하지 않습니다. 이 문제를 해결하려면 다음을 사용할 수 있습니다 eval
.
b=value
a=b
eval aval=\$$a
echo $aval
출력은
value
나는 이것이 고대의 실이라는 것을 알고 있지만 여기에 내 2 센트가 있습니다.
다음은 필요한 기능을 허용하는 bash 함수입니다.
read_var() {
set | grep ^$1\\b | sed s/^$1=//
}
다음은 간단한 테스트 스크립트입니다.
#!/bin/bash
read_var() {
set | grep ^$1\\b | sed s/^$1=//
}
FOO=12
BAR=34
ABC_VAR=FOO
DEF_VAR=BAR
for a in ABC DEF; do
echo $a = $(read_var $(read_var ${a}_VAR))
done
예상대로 출력은 다음과 같습니다.
ABC = 12
DEF = 34
기본 이름 bultin이 도움이 될 수 있습니다. 특별히 한 부분으로 분할하고 있기 때문입니다.
user@host# var=/path/to/file.extension
user@host# basename ${var%%.*}
file
user@host#
두 줄 변형보다 실제로 빠르지는 않지만 기본 제공 기능을 사용하는 한 줄입니다. 또는 패턴 중첩 작업을 수행 할 수있는 zsh / ksh를 사용하십시오. :)
OP의 원래 질문에 대한 한 줄 솔루션이 있습니다. 파일 확장자가 제거 된 스크립트의 기본 이름입니다.
progname=$(tmp=${0%.*} ; echo ${tmp##*/})
여기에 또 다른 것이 있지만 basename에 치트를 사용합니다.
progname=$(basename ${0%.*})
Other answers have wandered away from the OP's original question and focused on whether it's possible to just expand the result of expressions with ${!var}
but came across the limitation that var
must explicitly match an variable name. Having said that, there's nothing stopping you having a 1-liner answer if you chain the expressions together with a semicolon.
ANIMAL=CAT
BABYCAT=KITTEN
tmp=BABY${ANIMAL} ; ANSWER=${!tmp} # ANSWER=KITTEN
If you want to make this appear like a single statement, you can nest it in a subshell, i.e.
ANSWER=$( tmp=BABY${ANIMAL) ; echo ${!tmp} ) # ANSWER=KITTEN
An interesting usage is indirection works on arguments of a bash function. Then, you can nest your bash function calls to achieve multilevel nested indirection because we are allowed to do nested commands:
Here's a demonstration of indirection of an expression:
deref() { echo ${!1} ; }
ANIMAL=CAT
BABYCAT=KITTEN
deref BABY${ANIMAL} # Outputs: KITTEN
Here's a demonstration of multi level indirection thru nested commands:
deref() { echo ${!1} ; }
export AA=BB
export BB=CC
export CC=Hiya
deref AA # Outputs: BB
deref $(deref AA) # Outputs: CC
deref $(deref $(deref AA)) # Outputs: Hiya
If the motivation is to "obfuscate" (I would say streamline) array processing in the spirit of Python's "comprehensions", create a helper function that performs the operations in sequence.
function fixupnames()
{
pre=$1 ; suf=$2 ; shift ; shift ; args=($@)
args=(${args[@]/#/${pre}-})
args=(${args[@]/%/-${suf}})
echo ${args[@]}
}
You can use the result with a nice one-liner.
$ echo $(fixupnames a b abc def ghi)
a-abc-b a-def-b a-ghi-b
Though this is a very old thread, this device is ideal for either directly or randomly selecting a file/directory for processing (playing tunes, picking a film to watch or book to read, etc).
In bash I believe it is generally true that you cannot directly nest any two expansions of the same type, but if you can separate them with some different kind of expansion, it can be done.
e=($(find . -maxdepth 1 -type d))
c=${2:-${e[$((RANDOM%${#e[@]}))]}}
Explanation: e is an array of directory names, c the selected directory, either named explicitly as $2,
${2:-...}
where ... is the alternative random selection given by
${e[$((RANDOM%${#e[@]}))]}
where the
$((RANDOM%...))
number generated by bash is divided by the number of items in array e, given by
${#e[@]}
yielding the remainder (from the % operator) that becomes the index to array e
${e[...]}
Thus you have four nested expansions.
It will work if you follow the bellow shown way of taking on intermediate step :
export HELLO="HELLO"
export HELLOWORLD="Hello, world!"
varname=${HELLO}WORLD
echo ${!varname}
eval will allow you to do what you are wanting:
export HELLO="HELLO"
export HELLOWORLD="Hello, world!"
eval echo "\${${HELLO}WORLD}"
Output: Hello, world
ReferenceURL : https://stackoverflow.com/questions/917260/can-var-parameter-expansion-expressions-be-nested-in-bash
'developer tip' 카테고리의 다른 글
Lambda 함수 내에서 직접 Thread # sleep ()을 호출 할 수없는 이유는 무엇입니까? (0) | 2020.12.15 |
---|---|
오류 : 메소드의 서명 없음 : com.crashlytics.tools.gradle.CrashlyticsPlugin.findObfuscationTransformTask () (0) | 2020.12.15 |
파이썬 문자열에서 빈 줄을 제거하는 빠른 한 줄은 무엇입니까? (0) | 2020.12.15 |
Grails 애플리케이션의 세션 시간 제한을 구성하는 방법은 무엇입니까? (0) | 2020.12.15 |
문자열의 첫 번째 문자를 축소하는 방법은 무엇입니까? (0) | 2020.12.15 |