スクリプトがありますequijoin2
。
#! /bin/bash
# default args
delim="," # CSV by default
outer=""
outerfile=""
# Parse flagged arguments:
while getopts "o:td:" flag
do
case $flag in
d) delim=$OPTARG;;
t) delim="\t";;
o) outer="-a $OPTARG";;
?) exit;;
esac
done
# Delete the flagged arguments:
shift $(($OPTIND -1))
# two input files
f1="$1"
f2="$2"
# cols from the input files
col1="$3"
col2="$4"
join "$outer" -t "$delim" -1 "$col1" -2 "$col2" <(sort "$f1") <(sort "$f2")
そして2つのファイル
$ cat file1
c c1
b b1
$ cat file2
a a2
c c2
b b2
最後のコマンドが失敗するのはなぜですか?ありがとうございます。
$ equijoin2 -o 2 -d " " file1 file2 1 1
a a2
b b1 b2
c c1 c2
$ equijoin2 -o 1 -d " " file1 file2 1 1
b b1 b2
c c1 c2
$ equijoin2 -d " " file1 file2 1 1
join: extra operand '/dev/fd/62'
答え1
"$outer"
引用符で囲まれたスカラー変数なので、常に引数に展開されます。空でも設定されていなくても、空の引数(join
呼び出しスクリプトを使用するときは2つの引数ではなく1つ-o2
の引数)に展開されます。-a 2
-a
2
オプションではなく引数の後にオプションを受け入れるので、おそらくjoin
GNUです。join
空の場合、これは"$outer"
オプションではなく引数であり、それを起動しない-
ため、ファイル名として扱われ、join
予期しない3番目のファイル名が提供されたことについて文句を言います。
可変数の引数を持つ変数が必要な場合は、配列を使用してください。
outer=()
...
(o)
outer=(-a "$OPTARG");;
...
join "${outer[@]}"
ここでも次のことができます。
outer=
...
(o)
outer="-a$OPTARG";;
...
join ${outer:+"$outer"} ... <(sort < "$f1") <(sort < "$f2")
または:
unset -v outer
...
(o)
outer="$OPTARG";;
...
join ${outer+-a "$outer"} ...
zsh
(この機能はsh / kshエミュレーションを除いては機能しません。)
その他の注意事項:
join -t '\t'
動作しません。delim=$'\t'
TABテキストを次の場所に保存する必要があります。$delim
--
コマンドに任意の引数を渡すときに使用する(または可能であればリダイレクトを使用する)ことを忘れないでください。だからsort -- "$f1"
またはそのsort < "$f1"
代わりに良いですsort "$f1"
。- 算術拡張も分割+globの影響を受けるため、引用符()で囲む必要があります(環境から継承されていない拡張を使用してスクリプトの前半で変更しない
shift "$((OPTIND - 1))"
ため、ここでは問題ではありませんが、まだ良い習慣です)。 )。bash
$IFS
IFS