변수가 포함된 문자열을 명령으로 실행

변수가 포함된 문자열을 명령으로 실행

Bash 스크립트에서 문자열을 실행하려고 합니다. 문자열에는 변수가 포함되어 있습니다(따라서 상황에 따라 일부 CLI 매개변수를 대체할 수 있음).

문제는 포함 변수를 사용할 때 --argument=value모든 것이 충돌하여 오류가 발생한다는 것입니다.

Missing trailing-' in remote-shell command.

샘플 코드:

#!/bin/bash

rsync_path="/usr/bin/rsync -azhrP"
rsync_ssh_cmd="--rsh='ssh -o Compression=no'"

`$rsync_path /path/to/file $rsync_ssh_cmd username@localhost:/tmp`

이 코드에 마지막 문자열을 넣으면 echo괜찮아 보입니다. 그러나 스크립트에서 문자열을 실행하려고 하면 예상대로 실행되지 않습니다.

해결책을 찾았습니다. 시도해 보면 모든 것이 괜찮을 것입니다.

eval "my-command-string"

바꾸다

`my-command-string`

또는

(my-command-string)

왜 그럴까요? 어떻게 하면 사용을 피할 수 있나요(정말로 해야 할까요?) eval?

나는 bash 4.3.11(1)-release (x86_64-pc-linux-gnu)(Kubuntu 14.04.3)를 사용합니다.

답변1

좋아요 eval문자열을 두 번 평가하는 다른 방법을 찾아 이를 방지 할 수 있습니다 . 무엇을 하든 꼭 필요해요두 가지 평가귀하의 요청이파싱을 파싱하다.

내 말은:

this is 'a parsed" command string"'

^ 3으로 계산성격:

1: this 2: is 3: a parsed" command string"

3의 따옴표는 중요하지 않습니다. 전혀 중요하지 않습니다.단어의 특정 문자. '원래 명령줄에 사용된 구문 인용문했다이는 쉘의 파서가 해석하여 분리하기 때문에 중요합니다.단어. 그 안에 있는 모든 것은 단지 단어의 일부일 뿐입니다.

그러니 얻고 싶다면단어는 a에서 나왔습니다.하나의,준비된즉, 이를 쉘에 대한 입력으로 반환해야 합니다. 이것이 바로 쉘이 입력 시 입력 인용문을 처리하는 것입니다. 따옴표는 의미 있는 방식으로 입력을 이스케이프하고 구분하는 데 사용됩니다. Shell이 ​​이런 식으로 계속된다면 무의미하고 꽤 무서울 것입니다. 마지막으로모두입력은 0으로 평가됩니다!

그래서 당신은두 번째 검토. 처리하지 않기 때문에 $( 명령 대체에서 얻을 수 없습니다.)입력하다, 그들은 처리한다산출. 어떤 부작용$단어 확장이것을 더 많은 세대와 동일시할 수도 있습니다.성격그렇지 않습니다. 즉,대지-나뉘다.대지- 분할 $IFS하고*와일드카드쉘에 의해 실행됨뒤쪽에입력하다성격구문 분석 중에 이미 구분되었습니다.

지금 의 전체 목적 evalevalUat~처럼입력하다쉘이 입력으로 받은 문자열입니다. 이것은정확히이것이 올바른 도구이지만, 원한다면 다른 방법으로도 할 수 있습니다.

한 가지 방법은 .자신만의 결과물을 얻는 것입니다.

string="printf '<%s>\n' 'these are' 'some words' 'i will evaluate again'"
. /dev/fd/0 <<!
$string
!

이 예에서는 쉘평가하다~처럼입력하다그것은산출. 효과가있다:

<these are>
<some words>
<i will evaluate again>

다른 셸을 호출하여 출력을 입력으로 평가하면 됩니다.

sh -c "$string"

...결과는 동일합니다. 당신은 할 수지연쉘을 정의하여 입력하십시오 alias.

alias evaled="$string"
evaled

...동일한 출력.

최대직접방법은 다음과 같습니다

eval "$string"

효과는 다른 모든 예제와 거의 동일하지만 이번에는 실제로 명령을 사용하여 수행했습니다.명명 된내가하고 싶은 일을 위해.

eval사람들이 그것이 무엇을 하는지, 왜 사용해야 하는지 이해하지 못했기 때문에 나쁜 평가를 받았습니다. 문제는, 그 일의 효과를 이해하지 못한다면, 그것을 사용해서는 안 된다는 것입니다. 길을 잃기 쉽습니다. 명령이 평가됩니다.두 배— 이는 평소보다 더 많은 — 그리고하나이는 일반적으로 대부분의 사람들이 이 사이트를 탐색하기에 충분한 시간입니다.

따라서 eval이 경우 원하는 작업을 수행하려면 을 사용해야 합니다. 왜냐하면 수행하려는 작업은 eval문자열이기 때문입니다. 나는 판단하지 않는다eval더 좋은 방법이 있었으면 좋겠지만 문자열을 원 하지만 쉘 문자열의 내용을 원할 때댓글을 달았습니다.쉘 입력으로 eval.

답변2

포함된 따옴표로 인해 이 문제가 발생합니다.배쉬 FAQ

작업 환경은 다음과 같습니다.

#!/bin/bash

rsync_path="/usr/bin/rsync -azhrP"
rsync_ssh_cmd=(--rsh='ssh \-o Compression=no')
`$rsync_path /path/to/file $rsync_ssh_cmd  root@localhost:/tmp`

[개념의 증거]

[root@localhost ~]# bash -x  /tmp/c.sh
+ rsync_path='/usr/bin/rsync -azhrP'
+ rsync_ssh_cmd=(--rsh='ssh \-o Compression=no')
++ /usr/bin/rsync -azhrP /path/to/file --rsh=ssh '\-o' Compression=no root@localhost:/tmp
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/root/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /root/.ssh/id_rsa
root@localhost's password:

관련 정보