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

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

저는 쉘 스크립팅을 처음 접했지만 익스플로잇을 거의 완료했습니다.FTP 프로그램. 스크립트에서 문제가 있는 부분은 긴 명령 목록( 로 구분 ;)을 생성할 때입니다.

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

내가 알아차린 것은 tail스크립트에서 나중에 명령 문자열을 호출할 때가 아니라 for 루프가 반복될 때 프로그램(백틱으로 묶음)이 실행된다는 것입니다.

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

답변1

이건 좀 까다롭습니다. 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. 그러나 이것은 그것을 피하는 좋은 방법을 모르는 상황 중 하나입니다. 도움이 되었기를 바랍니다. 행운을 빌어요!

답변2

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

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

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

관련 정보