나중에 사용할 때가 아니라 문자열을 만들 때 문자열의 Bash 명령이 실행됩니다.


10

저는 쉘 스크립팅을 처음 접 했지만 lftp 프로그램을 사용하는 스크립트를 거의 완성했습니다 . 문제가있는 스크립트 부분은 긴 문자열을 만들 때입니다 (로 구분 ;).

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done

내가 주목하는 것은 tailfor 루프가 반복 될 때 백틱으로 래핑 된 프로그램이 실행되고 있지만 나중에 스크립트에서 명령 문자열을 호출 할 때는 실행되지 않는다는 것입니다.

불행히도 $ somefile의 내용은이 단계에서 검사 할 준비가되지 않았습니다. 문자열을 만들 때가 아니라 필요할 때 명령을 실행하려면 어떻게해야합니까?

답변:


8

이것은 조금 까다 롭습니다. Hauke가 제공 한 정보는 정확합니다. 사용 사례에 맞게 파싱하기 만하면됩니다.

가장 쉬운 방법은 변수 정의가 정의 할 때로 묶인 명령을 실행하지 않도록 $()구문을 피하면서 구문 을 사용 하는 것입니다. 주의해야 할 점 은 중첩 된 명령을 실행하기 위해 실제 실행시 쉘에서 최종 결과를 (를 통해 ) 다시 평가해야한다는 것입니다 .$$()eval

예제를 보는 것이 훨씬 쉽기 때문에이 예제를 선택하면 올바른 길을 찾을 수 있습니다.

for((i=0;i<10;i++)); do 
  date +%s.%N  # Print a timestamp (in format seconds.nanoseconds)
  test="echo \$(date +%s.%N)" # Save a command to do the same
  sleep 1      # Sleep for a second
  eval "$test" # Evaluate the command saved in variable 'test'
  echo         # Print a new line before the next iteration
done

위 예제의 샘플 출력은 다음과 같습니다 (1 회 반복으로 트리밍).

1398832186.133661344
1398832187.139076728

각 루프의 두 번째 타임 스탬프는 첫 번째 루프 후 약 1 초입니다. 반대로, 정의 $에서 이스케이프하지 않고 동일한 테스트를 수행 test하고를 제거 eval하면 두 타임 스탬프가 거의 일치합니다.

eval대부분의 상황에서 사용하는 습관을 들이지 마십시오 . 그러나 이것을 피하는 좋은 방법을 모르는 사람들 중 하나입니다. 잘하면 이것이 도움이됩니다. 행운을 빕니다!


고마워, $(...)Hauke가 제안한대로 사용하려고 했지만 백 슬래시가 핵심입니다.
— Ricky

도움이 된 것을 기쁘게 생각합니다. 그러나 여기서 중요한 eval점은 명령을 둘러싸 기 위해 큰 따옴표 ( ) 대신 $작은 따옴표 ( ') 를 이스케이프 처리하지 않고 사용하여 동일한 작업을 수행 할 수 있다는 것 "입니다.
— daBeamer

이제 Huake의 제안과 마찬가지로 lftp 프로그램에서 이것을 사용하려고하면 echo가 단순히 명령을 인쇄하면 실제로 실행되지 않습니다. 보다 구체적인 도움을 받으려면 메일 링리스트를 시도해야 할 수도 있습니다.
— Ricky

실행하려는 명령은 무엇입니까? echo지연 실행 중첩 명령의 출력을 포함하여 내용이 포함 된 문자열 을 원한다는 인상을 받았습니다 .
— daBeamer

1
@Ricky @HaukeLaging의 모든 요점에 동의해야합니다. 에 코드를 빼면 코드 echo가 작동하지 않으며 eval문자열이 아닙니다. 우리에게 더 적절한 모범이 있다면, 우리는 도울 수 있습니다.
— daBeamer

6

인용에는 몇 가지 수준이 있습니다. 큰 따옴표 ( "...") 보호 공백 및 여러 특수 문자 ( ~, &, |, ;, ...)하지만, 매개 변수 확장 및 명령 대체를 방지하지 않습니다.

'"위험한"문자 앞에 작은 따옴표 ( ) 또는 백 슬래시 가 필요합니다 .

일반적으로 : $(tail ...)백틱 대신에 사용을 고려해야 합니다. 백틱은 더 오래된 표준이지만 $()대부분의 사람들에게 문제를 일으키지 않는 너무 오래된 것에 대해 이야기하고 있습니다. 새 버전은 읽기 쉽고 중첩 될 수 있습니다. sx의 형식 문제는 물론 ...


빠른 답변 Hauke에 감사드립니다. 불행히도 백틱을 권장으로 대체하면 $(...)동일한 결과가 생성됩니다. 내 문자열이 정의되면 쉘이이를 실행합니다.
— Ricky

@Ricky 대체 제안이 아니 었습니다. 당신은 사용해야 $()하지만 어쨌든 작은 따옴표가 필요합니다.
— Hauke ​​Laging

그래서 그 캐릭터들의 조합이 내가 추구하는 것을 달성하지 못합니까?
— Ricky

@Ricky "작은 따옴표가 필요하다"에 대해 이해하기 어려운 것은 무엇입니까? 당신은 분명히 시도조차하지 않습니다.
— Hauke ​​Laging

실제로 나는했지만 작은 따옴표를 사용하면 에코는 해당 줄의 모든 것을 일반 문자열로 인쇄합니다. 예를 제공하는 것이 어려운 점은 무엇입니까?
— Ricky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.