arg 経由またはファイルが存在しない場合は、stdin からファイルを受け取る次のコードがあります。
file=
column=
pattern=
path=
cmd="echo"
while getopts "f:c:e:" opt; do
case $opt in
f) file="$OPTARG";;
c) column="$OPTARG";;
e) pattern="$OPTARG";;
*) echo "Usage: $0 -f [file] -c [column] -e [pattern]"
esac
done
if [ -z "$file" ]; then
file=$(cat)
fi
このアプローチの問題は、catがファイルではなくファイルでは機能しないことです。たとえば、stdoutからインポートした場合:
cat data.csv | ./read.sh -c 2 -e " Max"
これにより、次のことは実行できません。
cat "$file"
Bashスクリプトでは代わりにechoを使用する必要があります。
OTOH、ファイルであればcatを使用でき、すべてが大丈夫です。私の質問は、スクリプトがvar $fileが実際のファイル名かstdoutであるかを認識させる方法です。
編集:コメントと回答を考慮し、ユーザーが指定した列と正規表現を読み、標準入力または引数として渡されたファイルで考慮できるスクリプト全体をユーザーに提供する方法は次のとおりです。
#!/bin/bash
unset -v column pattern filepath
cmd=echo
DELIMITER=","
while getopts "f:c:e:" opt; do
case $opt in
f) file="$OPTARG";;
c) column="$OPTARG";;
e) pattern="$OPTARG";;
*) printf>&2 '%s\n' "Usag: $0 [-f file] [-c column] [-e pattern]"; exit 1
esac
done
if [ -z "$file" ]; then
file=$(cat)
elif [ -z "$column" ]; then
echo "column number neeeded!"
elif [ -z "$pattern" ]; then
echo "pattern needed!"
fi
if [ -f "$file" ]; then
cmd="cat"
fi
if [ "$column" -eq 5 ]; then
DELIMITER=":"
fi
"$cmd" "$file" | awk -v col="$column" -v pattern="$pattern" -v del="$DELIMITER" -F "$DELIMITER" '{
for (i=1;i<=NF;i++) {
if ( i == col && $i == pattern ) {
print $0
} else if ( del == ":" && $i == pattern ) {
print $0
}
}
}'
exit 0
動作しますが、正しいアプローチではないと確信しています。私のファイルで両方の操作を実行しようとしました。
cat data.csv | ./read.sh -c 2 -e "Max"
そして:
./read.sh -f data.csv -c 2 -e "Max"
上記のスクリプトは動作しますが、最適化はゲームの名前です!
ベストアンサー1
の場合はcat
標準-
入力を意味します。多くのシステムでは、このコマンドは同様/dev/stdin
にすべてのコマンドで動作しますが、cat
LinuxまたはCygwinでは/dev/stdin
stdinで開かれた同じファイルを指し、場合によってはstdinとまったく同じようには機能しません。
だからあなたはこれを行うことができます:
file=-
unset -v column pattern filepath
cmd=echo
while getopts f:c:e: opt; do
case $opt in
(f) file="$OPTARG";;
(c) column="$OPTARG";;
(e) pattern="$OPTARG";;
(*) printf>&2 '%s\n' "Usage: $0 [-f file] [-c column] [-e pattern]"; exit 1
esac
done
shift "$(( OPTIND - 1 ))"
cat -- "$file"
stdin()は一度だけ読むことができます-
。
また注:
- エラーはstderrに送信する必要があります。
echo
$0
任意のデータ(制御できないデータなど)には使用できません。[...]
同意したようにメッセージを使用してください。任意に選択できるしたがって、この場合は必須であることを示唆しています-f [file]
が、その引数はオプションなので、ここでは正しくありません。-f
path
スクリプトが最終的に解釈される可能性がある場合zsh
(sh
シミュレーションでない場合)、配列$path
変数に/$PATH
に似た変数名を指定しないでください。csh
tcsh
- パラメータが指定されていることを確認するには、nullテストを避ける必要があります。たとえば
-f ''
、代わりに初期化時に使用して変数が設定されていないことを確認し、後でまだ設定されていないことを確認します。あるいは、追加のブールフラグ変数を使用して、オプションが合格したかどうかを記録します。$file
-f
unset -v var
[ -z "${var+set}" ]
-
ユーザーがstdin以外の現在の作業ディレクトリから呼び出された実際のファイルを意味するファイルを渡すことを許可するには、それをハンドルに変換できます。-
./-
(f)
file=$(cat)
stdinで読み取ることができる内容を読み、それをfile
変数(メモリ内)に保存します。したがって、他の人が言ったように、変数名は取得する入力ファイルの内容であるため、少し誤解を招く可能性があります。しかしそれも壊すあなたが得ることは、$(...)
NUL文字を削除またはブロックするzshを除いて、すべての末尾の改行文字を削除したことです。echo
それを(任意のデータではなく)使用すると、自分でecho
ダメージを受けます。
ここでは逆のアプローチをとり、-f
stdinに引数として渡されたファイルを開くこともできます。
unset -v column pattern filepath
cmd=echo
while getopts f:c:e: opt; do
case $opt in
(f) exec < "$OPTARG";;
(c) column="$OPTARG";;
(e) pattern="$OPTARG";;
(*) printf>&2 '%s\n' "Usage: $0 [-f file] [-c column] [-e pattern]"; exit 1
esac
done
shift "$(( OPTIND - 1 ))"
cat
exec
ファイルを開くことができない場合、POSIX シェルは自動的に終了します。-f
割り当て時など、複数のオプションが渡された場合は、最後のオプションのみが考慮$file
されます。