스크립트에서! $를 사용할 수 없습니까?


11

왜 이것이 작동하지 않는지 궁금합니다.

#!/bin/bash 

ls /bin
ls !$

ls /bin두 번 실행 하지만 두 번째 !$는 해석되지 않은 오류가 발생합니다.

내가 뭔가를 그리워했거나 !$명령 줄에서만 작동 했습니까 ?

man bash(Mac에서) 관련 부분을 찾을 수 없습니다


9
이것이 실제로 스크립트에서 이것을 달성하는 가장 좋은 방법입니까? 대화 형이 아닌 방식으로 실행하는 이유로 인해 history는 기본적으로 비활성화되어 있습니다. 긴 스크립트가 .bash_history 파일을 스팸으로 만듭니다. 이 질문을 할 가치가 없다고 말하지는 않지만 스크립트에서 이것을 사용하려고 생각한다면 이것이 가장 좋은 방법입니까?
flungo

답변:


26

쉘이 비 대화식으로 실행될 때 히스토리히스토리 확장 은 기본적으로 사용되지 않습니다.

당신이 필요합니다 :

#!/bin/bash 

set -o history
set -o histexpand

ls /bin
ls !$

또는:

SHELLOPTS=history:histexpand bash script.sh

script.sh실행 가능한 모든 bash 인스턴스에 영향을줍니다 .


9
SHELLOPTS에주의를 기울이면 bash그 실행에 영향을 미치지 script.sh만 다른 스크립트 와 마찬가지로 결국 실행될 수 있는 다른 모든 bash인스턴스 에도 영향을 미칩니다 . script.shbash
Stéphane Chazelas

그리고 스크립트를 실행 하는 다른 인스턴스 에는 영향을 미치지 않습니다 . bash
Blacklight Shining

@ StéphaneChazelas의 의견을 편집하면이 답변이 향상 될 것이라고 생각합니다.
Oliphaunt-복직 모니카

7

제정신이 할 일은

ls /bin
ls $_

또는

set ls /bin
$*
$*

또는

c='ls /bin'
$c
$c

주의 사항 : 각 함정에는 함정이 있음을 기억해야합니다. $ _ 솔루션은 마지막 단일 인수 만 캡처하므로 ls foo bar$ _에 just가 포함 bar됩니다. 사용 한 set(인수 우선합니다 $1, $2등). 그리고 작성된 모든 것이 작동하지만 더 복잡한 명령 (이스케이프 및 공백 문제)으로 일반화되면 어려움이 발생할 수 있습니다. 예를 들면 다음과 같습니다 ls 'foo bar'(단일 경로 이름 인수 foo bar 이상의 공백 또는 다른 공백 문자가 포함되어 있음)는이 두 가지 예에서 올바르게 작동하지 않습니다. 이러한 경우를 해결하려면 적절한 이스케이프 처리 ( eval명령 과 결합 ) 또는 "$@"대신 사용 $*이 필요할 수 있습니다.


1
휴대가 가능하고 대화식 사용을보다 쉽게하기위한 bashism을 남용하지 않는 답변은 +1입니다. (기본 설정에서 느낌표를 대화식으로 확장하려는 bash의 욕망은 다른 쉘의 사용자처럼 반 직관적이며, 복잡한 쉘 명령을 수행하려고 할 때 항상 나를 망치기 때문에 비생산적입니다 ).
mtraceur

이 시점에서 작성된 것처럼, 초보자 쉘 스크립터가 더 복잡한 명령으로 일반화하려고 할 때 발생할 수있는 문제로 인해 +1을 주저했습니다. 나는 가능한 함정을 설명하는 경고문을 적어도 추가하도록 편집을 제안했다.
mtraceur

@mtraceur : 이식성이 없으며 bash, zsh, ksh에서만 작동합니다 (두 명령이 같은 줄에 있지 않은 경우). 대화식
cuonglm

@cuongim : 죄송합니다. 아마 너무 부주의하게 일반인이었습니다. $_방법은 이식 할 수 없습니다, 당신은 맞다. 이 set접근 방식은 비 대화식 대시에서 작동 하며 일부 (오래된) 쉘로 완벽하게 이식 할 수없는 역사 ${1+"$@"}set가지고 있음 을 모호하게 기억하지만 (+ zsh 전역 별칭) 트릭을 사용하는 것이 일반적이어야합니다 . 특히 적절한 이스케이프 및 실제 eval명령을 사용하여 변수 정의 홀드 명령 및 그 이후 평가 방식 은 내가 아는 한 완전히 이식 가능합니다.
mtraceur
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.