Bash에서 유틸리티 프로그램에 대한 체인 호출을 매개 변수화


12

stdin에서 데이터 열을 읽고 처리하고 (다듬기 효과 적용) stdout으로 출력하는 Bash 셸에서 사용되는 블랙 박스 UNIX 프로그램이 있습니다. 나는 유닉스 파이프로 사용합니다.

generate | smooth | plot  

더 매끄럽게하기 위해 매끄럽게 반복 할 수 있으므로 Bash 명령 줄에서 다음과 같이 호출됩니다.

generate | smooth | smooth | plot   

또는

generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot

이것은 부실 해지고있다. Bash 래퍼를 파이프에 연결 smooth하고 출력을 smooth임의의 횟수의 새 인스턴스에 즉시 다시 공급하고 싶습니다.

generate | newsmooth 5 | plot

대신에

generate | smooth | smooth | smooth | smooth | smooth | plot

첫 번째 시도는 현재 디렉토리에서 임시 파일을 생성하고 삭제 한 Bash 스크립트 였지만 쓰기 액세스 권한이있는 디렉토리에 있지 않을 때 추악하게 바뀌었고 중단되면 가비지 파일을 남겼습니다.

smooth프로그램에 대한 주장은 없습니다 .

이러한 프로그램을 "포장"하여 호출 횟수를 매개 변수화하는보다 우아한 방법이 있습니까?


1
나는 당신의 예는 질문의 이익을위한 강제 경우가 아닌 실제 필요 희망
arielnmz

답변:


18

재귀 함수로 래핑 할 수 있습니다.

smooth() {
  if [[ $1 -gt 1 ]]; then # add another call to function
    command smooth | smooth $(($1 - 1)) 
  else
    command smooth # no further 
  fi
}

이것을 다음과 같이 사용합니다

generate | smooth 5 | plot

어느 것이

generate | smooth | smooth | smooth | smooth | smooth | plot

이것은 완벽하고 필요에 따라 정확하게 동작합니다. 그리고 bash "command"키워드에 대해 배웠습니다.
Diane Wilbor

2
우연히, 이것은 임의로 긴 파이프 체인을 어떻게 코딩합니까? 에서 사용하는 것과 동일한 접근 방식 입니다. 그리고 그보다 훨씬 전에 xmlstarlet에서 긴 편집 목록을 처리 합니다.
찰스 더피

5

smooth원하는 명령 수 만큼 쉼표를 입력 할 수 있으면 쉘의 쉼표로 구분 된 Brace Expansion을 활용할 수 있습니다.

TL; DR

샘플 사례의 전체 명령 줄은 다음과 같습니다.

generate | eval 'smooth |'{,,,,} plot

노트 :

  • 반복 횟수를 줄이려면 쉼표를 추가하거나 제거하십시오. smooth |
  • Brace Expansion에서 생성 한 마지막 문자열에 포함되어 있기 때문에 |이전 에는 없습니다plotsmooth |
  • smooth열린 중괄호 앞에 따옴표로 묶인 고정 부분 내에 올바로 포함 할 수있는 한에는 인수를 제공 할 수도 있습니다. 어쨌든 당신은 그것들을 명령의 모든 반복에 제공한다는 것을 기억하십시오

작동 원리

쉼표로 구분 된 Brace Expansion을 사용하면 지정된 고정 부품과 지정된 가변 부품으로 구성된 문자열을 동적으로 생성 할 수 있습니다. produce와 같이 변수 부분이 표시되는만큼 문자열을 a{b,c,d}생성합니다 ab ac ad.

여기서 약간의 트릭은 가변 부품 의 목록을 작성하는 것입니다 ( 예 : 중괄호 안에 쉼표 만있는 경우) Brace Expansion은 고정 부품의 사본 만 생성합니다. 예를 들어 :

smooth{,,,,}

생산할 것이다 :

smooth smooth smooth smooth smooth

참고 4 개 쉼표 5 생산 smooth문자열을. 이것이 Brace Expansion의 작동 방식입니다. 쉼표에 1을 더한 문자열을 생성합니다.

물론 귀하의 경우에는 |각각을 분리 해야 smooth하므로 고정 부분에 추가하고 쉘이 한 번에 해석 하지 못하도록 올바르게 인용하십시오 . 그건:

'smooth|'{,,,,}

생산할 것이다 :

'smooth|' 'smooth|' 'smooth|' 'smooth|' 'smooth|'

고정 부품은 항상 열린 브레이스에 바로 인접하여 배치하십시오 . 즉와 ' 와 사이에 공간이 없어야 합니다 {.

(고정 부품을 구성하려면 고정 부품에서 쉘 변수를 확장해야하는 경우 작은 따옴표 대신 큰 따옴표를 사용할 수도 있습니다. 일부 쉘의 특수 문자가 발생할 때 필요한 추가 이스케이프를 처리하십시오. 큰 따옴표로 묶인 문자열 내부).

이 시점 eval 에서 쉘이 최종적으로 파이프 라인 명령으로 해석되도록하려면 해당 문자열에 적용 해야 합니다.

따라서 요약하자면 샘플 사례의 전체 명령 줄은 다음과 같습니다.

generate | eval 'smooth |'{,,,,} plot

1
호출이 매개 변수화 된 장소에서 사용되는 경우 보안에 심각한 우려가 있습니다. 재귀 bash 함수 대 반복적 인 "eval"문자열 작성 에 대한 내 대답을 참조하십시오 . 스택 오버플로 이상.
Charles Duffy

1
@CharlesDuffy 나는 eval신뢰할 수 있고 비 위생적이며 평가할 문자열을 제공 할 때, 즉 연결된 사례와 같이 "알 수없는"내용을 전달할 수있는 변수와 함께 사용될 때 사용 에 대한 묵시적 위험에 대한 귀하의 우려에 전적으로 동의 합니다. 반면에 eval, 특히 프롬프트에서 사용될 때 명령의 빠른 "배관"에 매우 편리 할 수 ​​있습니다. 예를 들어, eval입력은 사용자가 직접 입력 한 리터럴 문자열 일 것입니다. 사람
LL3 2016 년

이미 다른 곳에서 본 것처럼 항상 eval str소박하고 어리석은 것으로 바꿀 수 있습니다 . /dev/stdin <<<str. 뿐만 아니라이 그것은 또한 ;-) 허리 떨어져 @CharlesDuffy를 유지합니다, 바보에 인상을 만들 것입니다
pizdelect

1
@pizdelect, 당신은 LL3의 이전 의견을주의 깊게 읽을 수 있습니다-그것은 균형 있고, 미묘하고 현명합니다. (실제로 초기 의견에는 무시하고있는 뉘앙스가있었습니다. "호출이 매개 변수화 된 경우에 사용되는 경우"는 중요한 차이점입니다. LL3의 인스턴스 매개 변수화 되지 않아 안전합니다.
찰스 더피
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.