我经常做这样的操作
paste <(cut -d, -f1 file1.csv) <(cut -d, -f1 file2.csv)
Run Code Online (Sandbox Code Playgroud)
这对于多个文件来说非常乏味。
我可以自动化这个过程,例如使用通配符吗?我可以保存cut
结果
typeset -A cut_results
for f in file*.csv; do
cut_results[$f]="$(cut -d, -f1 $f)"
done
Run Code Online (Sandbox Code Playgroud)
但我不确定如何从那里开始。
您可以使用 globbing 自动执行此操作,特别是e
glob qualifier , plus eval
,但它不漂亮而且引用很棘手:
eval paste *.csv(e\''REPLY="<(cut -d, -f1 $REPLY)"'\')
Run Code Online (Sandbox Code Playgroud)
\'…\'
是为 glob 的每个匹配执行的一些代码。它与REPLY
设置为匹配的变量一起执行,并且可以修改它。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)^@})"
}
Run Code Online (Sandbox Code Playgroud)
示例用法(语法让人想起zargs
):
map paste -- cut -d, -f1 -- *.csv
Run Code Online (Sandbox Code Playgroud)