Programing

출력을 bash 함수로 파이프

crosscheck 2020. 11. 23. 07:47
반응형

출력을 bash 함수로 파이프


bash 스크립트에 간단한 기능이 있으며 stdout을 입력으로 파이프하고 싶습니다.

jc_hms(){
  printf "$1"
}

이런 식으로 사용하고 싶습니다.

var=`echo "teststring" | jc_hms`

물론 중복 함수 echo 및 printf를 사용하여 질문을 단순화했지만 아이디어를 얻었습니다. 지금은 "찾을 수 없음"오류가 발생하는데, 이는 내 매개 변수 구분이 잘못되었음을 의미합니다 ( "$ 1"부분). 어떤 제안?

원래 jc_hms 함수는 다음과 같이 사용되었습니다.

echo `jc_hms "teststring"` > //dev/tts/0

그러나 직렬 포트로 보내기 전에 먼저 추가 처리를 위해 결과를 변수에 저장하고 싶습니다.

편집 : 그래서 명확히하기 위해, 직렬 포트에 물건을 인쇄하려고하지 않습니다. "|" 파이프 문자이며 이것이 가능한지 궁금합니다.

편집 : 좋아, 여기에 전체 기능이 있습니다.

jc_hms(){
  hr=$(($1 / 3600))
  min=$(($1 / 60))
  sec=$(($1 % 60))

  printf "$hs:%02d:%02d" $min $sec
}

이 코드 줄에 나오는 문자열을 형성하는 함수를 사용하고 있습니다.

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring

$ songtime은 공백으로 구분 된 "총 재생 시간"으로 표현되는 문자열입니다.

이걸 한 줄로하고 awk 후에 파이프하면 좋겠어

printstring=`echo $songtime | awk '{print S1 }' | jc_hms`

그렇게.


실제 질문에 답하기 위해 쉘 함수가 파이프의 수신 끝에있을 때 함수 내에서 실행되는 첫 번째 명령이 표준 입력을 읽습니다. 이후 printf함수의 최초이자 유일한 명령입니다, 표준 입력은 무시됩니다. read내장 을 사용하여 표준 입력을 printf다음 으로 전달할 수있는 변수로 읽는 것을 포함하여 여러 가지 방법 이 있습니다 .

jc_hms () {
    read foo
    hr=$(($foo / 3600))
    min=$(($foo / 60))
    sec=$(($foo % 60))
    printf "%d:%02d:%02d" "$hr" "$min" "$sec"
}

그러나 파이프 라인에 대한 필요성은 사용에 대한 인식 된 필요성에 따라 달라 지므로 awk다음 대안을 제안하겠습니다.

printstring=$( jc_hms $songtime )

songtime공백으로 구분 된 숫자 쌍으로 구성되어 있으므로 쉘은의 값에 대해 단어 분할을 수행 songtime하고 jc_hms두 개의 개별 매개 변수를 확인합니다. 이는의 정의를 변경할 필요가 없으며 jc_hms표준 입력을 통해 아무것도 파이프 할 필요가 없습니다.

여전히 jc_hms표준 입력을 읽어야 하는 다른 이유가있는 경우 알려주십시오.


이와 같은 bash 함수에 직접 파이프를 연결할 수는 없지만 read대신 끌어 오기 위해 사용할 수 있습니다 .

jc_hms(){
  while read data; do
      printf "%s" "$data"
  done
}

당신이 원하는 것이되어야합니다


1) 나는 이것이 꽤 오래된 게시물이라는 것을 안다.

2) 여기 대부분의 답변이 마음에 듭니다.

그러나 비슷한 것이 필요했기 때문에이 게시물을 찾았습니다. 모두가 stdin을 사용해야한다는 데 동의하지만 여기에 누락 된 답변은 / dev / stdin 파일의 실제 사용입니다.

Using the read builtin forces this function to be used with piped input, so it can no longer be used in a typical way. I think utilizing /dev/stdin is a superior way of solving this problem, so I wanted to add my 2 cents for completeness.

My solution:

jc_hms() { 
  declare -i i=${1:-$(</dev/stdin)};
  declare hr=$(($i/3600)) min=$(($i/60%60)) sec=$(($i%60));
  printf "%02d:%02d:%02d\n" $hr $min $sec;
}

In action:

user@hostname:pwd$ jc_hms 7800
02:10:00
user@hostname:pwd$ echo 7800 | jc_hms 
02:10:00

I hope this may help someone.

Happy hacking!


Or, you can also do it in a simple way.

jc_hms() {
    cat
}

Though all answers so far have disregarded the fact that this was not what OP wanted (he stated the function is simplified)


I like user.friendly's answer using the Bash built-in conditional unset substitution syntax. Here's a slight tweak to make his answer more generic, such as for cases with an indeterminate parameter count:

function myfunc() {
    declare MY_INPUT=${*:-$(</dev/stdin)}
    for PARAM in $MY_INPUT; do
        # do what needs to be done on each input value
    done
}

Hmmmm....

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring

if you're calling awk anyway, why not use it?

printstring=`TZ=UTC gawk -vT=$songplaytime 'BEGIN{print strftime("%T",T)}'`

I'm assuming you're using Gnu's Awk, which is the best one and also free; this will work in common linux distros which aren't necessarily using the most recent gawk. The most recent versions of gawk will let you specify UTC as a third parameter to the strftime() function.

참고URL : https://stackoverflow.com/questions/11454343/pipe-output-to-bash-function

반응형