ユーザー入力がパイプから来るのか、パラメータを使って入ってくるのかをどのように検出できますか? (例:「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"; donecmd | 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

関連情報