사용자 입력이 파이프에서 오는지 또는 매개변수를 사용하여 들어오는지 어떻게 감지할 수 있나요? (예: "if else" 사용)

사용자 입력이 파이프에서 오는지 또는 매개변수를 사용하여 들어오는지 어떻게 감지할 수 있나요? (예: "if else" 사용)

사용자 입력이 파이프에서 오는지 또는 매개변수를 사용하여 들어오는지 어떻게 감지할 수 있나요? (예: "if else" 사용)

예:

파이프라인이 있다

$ cat input_file | ./example.sh
hello
world

매개변수 포함

$ ./example.sh "hello" "world"
hello
world

내 오류 코드:

URL 슬러그 쉘 스크립트를 작성했습니다. URL 구문 분석을 위한 스크립트에 함수가 있습니다. 저는 이 함수를 파이프 cat a | ./example.sh나 사용자 입력 에 사용합니다 ./example.sh "hello" "world". 내 코드는 정확하지만 사용자 입력이 파이프인지 매개변수인지 감지하고 확인하는 방법을 이해할 수 없습니다.

내 영어로 미안해

#!/bin/bash

# define replacements
declare -a repls=(
    "Ğg"
    "ğg"
    "Çc"
    "çc"
    "Şs"
    "şs"
    "Üu"
    "üu"
    "Öo"
    "öo"
    "İi"
    "ıi"
    " -"
    "--"
)

function slug() {
    slug=""

    for (( i=0; i<${#arg}; i++ )) 
    do
        char="${arg:$i:1}"
        ascii=$(printf "%d" "'$char")

        # if alphanumeric
        # locale encoding should be UTF-8 for this values to work
        if [[ ( $ascii -ge 48 && $ascii -le 57 ) || # numbers
            ( $ascii -ge 65 && $ascii -le 90 ) ||  # uppercase
            ( $ascii -ge 97 && $ascii -le 122 ) ]]; then # lowercase
            slug="$slug$char"
        else
            for (( j=0; j < ${#repls[@]}; j++ ))
            do
                from=${repls[$j]:0:1}
                to=${repls[$j]:1:1}
                if [[ $char == $from ]]; then
                    slug="$slug$to"
                    break
                fi
            done
        fi
    done

    if [[ $slug == "" ]]; then
        echo "words should contain at least one valid character"
        exit 1
    fi

    echo $slug | awk '{print tolower($0)}'
}

#FOR PARAMETERS
for arg in "$@"
do
 slug;
done

##FOR READ PIPE
[[ -z "$@" ]] && while read arg;
do
 slug;    
done

답변1

나는 그것을 할 것이다:

something_with() {
  printf 'Processing "%s"\n' "$1"
}

ret=0
if [ "$#" -gt 0 ]; then
  # process args on command line

  for arg do
    something_with "$arg" || ret=$?
  done
else
  # no arg, processing lines of stdin instead:

  while IFS= read -r "$arg" || [ -n "$arg" ]; do
    # redirect something_with's stdin to /dev/null to make sure
    # it doesn't interfere with the list of args.
    </dev/null something_with "$arg" || ret=$?
  done
fi

exit "$ret"

(이것은 stdin을 통해 전송된 매개변수에 개행 문자가 포함될 수 없음을 의미합니다.)

입력을 매개변수로 사용할 수도 있지만 다음과 같이 스크립트를 호출합니다.

xargs -rd '\n' -a input_file your-script

(여기서는 GNU로 가정 )은 행의 내용을 인수로 전달하는 xargs데 사용됩니다 (이 경우 최대 명령 인수 수에 대한 제한을 해결 하기 위해 여러 번 호출할 수 있습니다 ).xargsinput_fileyour-scriptyour-scriptxargs

어쨌든 여기서는 stdin이 파이프인지 확인하고 싶지 않다고 말하고 싶습니다.

  1. 우선 cat input_file | your-script이것은고양이의 쓸모없는 사용(악명 높은 UUoC). 일반적으로 파일 내용을 명령에 대한 입력으로 사용하려면 < input_file your-scrip또는 를 사용합니다. your-script < input_file이 경우 스크립트의 표준 입력은 파이프가 아닙니다( input_file그 자체가 명명된 파이프가 아닌 한).

  2. 스크립트를 읽지 않으려는 경우에도 파이프에 연결된 stdin을 사용하여 스크립트를 호출할 수 있습니다. 예를 들어 ssh host your-script arg1 arg2(stdin aa 파이프라인은 sshd) 또는 ... | while IFS= read -r foo; do your-script "x$foo"; done( cmd | xargs your-script일부 xargs구현의 경우 일부는 stdin을 /dev /null로 리디렉션함)

하지만 정말로 그렇게 하고 싶다면 이 사이트의 별도 질문에서 이미 이에 대한 내용을 다루고 있습니다.프로그램은 stdout이 터미널이나 파이프에 연결되어 있는지 어떻게 알 수 있습니까?차이점은 이것이 stdout이 아닌 stdin이므로 파일 설명자가 1이 아닌 0이라는 것입니다.

답변2

$-변수 또는 변수를 통해 쉘이 대화형인지 확인할 수 있습니다 $PS1.

case "$-" in
*i*)    echo This shell is interactive ;;
*)  echo This shell is not interactive ;;
esac

또는

if [ -z "$PS1" ]; then
        echo This shell is not interactive
else
        echo This shell is interactive
fi

위의 예는 다음에서 복사되었습니다.여기.

@Kusalananda에게 감사드립니다: 매개변수가 스크립트의 다른 옵션으로 연결되어 있는지 확인하세요.

if [ -t 0 ]; then
  echo "This shell is interactive"
fi

관련 정보