私はこれを頻繁にします
paste <(cut -d, -f1 file1.csv) <(cut -d, -f1 file2.csv)
複数のファイルの場合、これは非常に退屈な作業です。
たとえば、ワイルドカードを使用してこのプロセスを自動化できますか?cut
結果を保存できます。
typeset -A cut_results
for f in file*.csv; do
cut_results[$f]="$(cut -d, -f1 $f)"
done
しかし、そこからどのように行くのかわかりません。
答え1
特にワイルドカードを使用して自動化できます。e
グローバル予選、 plus eval
、しかし、ビューによくない参照するのは難しいです。
eval paste *.csv(e\''REPLY="<(cut -d, -f1 $REPLY)"'\')
- その間の部分は、
\'…\'
各マッチングに対してグローバルに実行されるいくつかのコードです。REPLY
一致するように設定された変数で行われ、修正が可能です。 - globを解析するときに拡張しないように、コードを一重引用符で囲みました。
- 一致する場合、コードは
REPLY="<(cut -d, -f1 $REPLY)"
文字列を生成します。コードの実行時に置き換えられた値に加えて、等号の後の部分が拡張されないように二重引用符が必要です。<(cut -d, -f1 file1.csv)
file1.csv
e
REPLY
- 各ワイルドカードファイルは文字列に置き換えられます。
機能の複雑さを隠すことをお勧めします。最小限のテストを受けました。
function map {
emulate -LR zsh
local cmd pre
cmd=()
while [[ $# -ne 0 && $1 != "--" ]]; do
cmd+=($1)
shift
done
if ((!$#)); then
echo >&2 "Usage: $0: COMMAND [ARGS...] -- PREPROCESSOR [ARGS...] -- FILES..."
return 125
fi
shift
while [[ $# -ne 0 && $1 != "--" ]]; do
pre+="${(q)1} "
shift
done
if ((!$#)); then
echo >&2 "Usage: $0: COMMAND [ARGS...] -- PREPROCESSOR [ARGS...] -- FILES..."
return 125
fi
shift
eval "${(@q)cmd}" "<($pre${(@q)^@})"
}
使用例(構文は次のことを思い出させますzargs
):
map paste -- cut -d, -f1 -- *.csv
答え2
私はあなたの最初の行が単純な1行ほど良いと思います。
名前の異なる複数のファイルがある場合は、単純な履歴拡張「チート」を使用して重複入力を減らすことができます。
最初の実行<(cut -d, -f1
末尾のスペースに注意してください。また、このコマンドはCtrl-を押すだけで補助プロンプトが表示されることに注意してくださいC。唯一のことは歴史に追加することです。
次の実行paste !!file1.csv) !!file2.csv)
!!
末尾の空白を含む、前のコマンド実行の全内容に拡張されます。末尾の閉じ括弧を忘れた場合は、補助プロンプトが表示されます。その場合は、Ctrl-と入力してCもう一度やり直してください。
少し古いですが、使い捨てで使用するのに十分です。これを頻繁に行うと、bash関数を書くことができます。
答え3
努力するアッ
awk '{L[FNR]=L[FNR] $1 "\t"}END{for(i=1;i<=FNR;i++)print L[i]}' *.csv
または生地そしてsed
paste *.csv | sed 's/ [^\t]*//g'
答え4
あなたの主張が次のと仮定すると、次のようになり"$@"
ます。
eval "paste $(printf "<( cut -d, -f1 %q ) " "$@")"
それは行わなければなりません。