셸 함수: 파이프 시퀀스를 인수로 사용

셸 함수: 파이프 시퀀스를 인수로 사용

임시 파일을 생성하고 매개 변수(모든 파이프 시퀀스 포함)를 실행하고 이를 임시 파일로 리디렉션한 다음 VS Code에서 여는 셸 함수(.bashrc)가 있습니다.

나는 쉘 함수를 다음과 같이 호출합니다.

Temp "ls | nl"

아래 코드에서는 이를 작동시키려고 합니다. IFS를 공백으로 사용하여 전체 문자열을 분리하고 배열에 저장합니다. 이제 전체 파이프라인 시퀀스를 실행하고 최종 stdout을 임시 파일로 리디렉션하고 싶습니다. 이 목표를 어떻게 달성할 수 있나요? for 루프가 여기서 작동하지 않는다는 것을 알고 있습니다. 하지만 전체 배열을 인쇄하고 싶습니다.

Temp() {
    a="$(mktemp --suffix=.md "/tmp/$1-$(GetFilename "$2")-XXX")"
    IFS=' ' read -r -a Array <<< "$1"
    nArray=${#Array[@]} # Size of array
    for ((i=0; i<nArray; i=i+1)); do

    done
    #"${@}" > "$a"
    code -r "$a"
}

대화형 터미널 세션에서는 다음이 작동합니다.

cat <<EOF
$(ls | nl)
EOF

그래서 함수 내부의 for 루프 대신 Heredoc을 사용해 보았습니다.

cat > "$a" <<EOF
$($1)
EOF

그러나 이것은 주위에 따옴표를 붙이므로 |실패합니다.

위의 접근 방식은 어떻게든 따옴표를 제거할 수 있다면 효과가 있을 것입니다.


이것도 작동하지 않습니다

cat > "$a" <<EOF
$(echo $1 | sed "s/'//g")
EOF

답변1

함수가 인수로 주어진 쉘 명령을 실행하도록 하려면 eval문자열에서 이를 사용해야 합니다(예: print ) FOO.

eval_arg() {
    eval "$1"
}
eval_arg "echo foo |tr a-z A-Z"

"$1"매개변수 확장 후에는 파이프, 따옴표, 리디렉션 등의 셸 구문이 처리되지 않으므로 단순한 확장은 작동하지 않습니다. 첫 번째 인수를 배열로 분할하거나 $@실제로 변경하지는 않습니다.


따라서 $(ls | nl)셸에서 처리되는 리터럴 파이프 문자가 있지만 $($1)값의 특수 문자 $1(단어 분리기 및 와일드카드 제외)는 에서 처리되지 않습니다. 여기에는 따옴표가 없습니다.

마지막 예에서는 $(echo $1 | sed "s/'//g")값을 공백으로 분할한 다음(기본 단어 분할 사용) 단어를 공백( )으로 연결하고 입력으로 전달한 후 그 안의 작은따옴표를 제거합니다.$1IFSechosed

그러므로:

$ set -- "'foo  bar'"
$ $(echo $1 | sed "s/'//g")
foo bar 

명령의 외부 따옴표는 set셸에서 처리되는 반면 내부 따옴표는 값의 일부입니다. 이로 set -- 'foo bar'인해 따옴표가 포함되지는 않으며 $1여기에 있는 유일한 따옴표는 일반적인 쉘 처리의 일부로 제거됩니다.

관련 정보