我有一个包含以下命令的文件
cat /some/dir/with/files/file1_name.tsv|awk -F "\\t" '{print $21$19$23$15}'
cat /some/dir/with/files/file2_name.tsv|awk -F "\\t" '{print $2$13$3$15}'
cat /some/dir/with/files/file3_name.tsv|awk -F "\\t" '{print $22$19$3$15}'
当我遍历文件以运行命令时,我得到以下错误
cat file | while read line; do $line; done
cat: invalid option -- 'F'
Try `cat --help' for more information.
答案 0 :(得分:1)
您没有按预期正确执行命令。由于您在文件上逐行阅读(原因不明),您可以直接调用解释器,如下所示
#!/bin/bash
# ^^^^ for running under 'bash' shell
while IFS= read -r line
do
printf "%s" "$line" | bash
done <file
但这会产生为文件的每一行创建一个新进程的开销。如果file
下的命令无害并且可以一次性运行,那么就可以
bash file
并完成它。
另外,对于使用awk
,只需对每一行执行以下操作,以避免无用cat
awk -F "\\t" '{print $21$19$23$15}' file1_name.tsv
答案 1 :(得分:0)
您期望管道(|
)符号按照您习惯的方式行事,但它并不适用。为了帮助您理解,请尝试以下方法:
A="ls / | grep e" # Loads a variable with a command with pipe
$A # Does not work
eval "$A" # Works
在不使用eval
的情况下展开变量时,在shell解释重定向和管道之后会发生扩展和单词拆分,因此管道符号只能作为文字字符显示。
您有一些选择:
A)通过将文件名作为参数传递来避免管道
awk -F "\\t" '{print $21$19$23$15}' /some/dir/with/files/file1_name.tsv
B)如下所示使用eval
,我建议您研究潜在的安全隐患。
C)将参数放入file
并解析它,避免使用eval
,例如:
# Assumes arguments separated by spaces
IFS=" " read -r -a arguments;
awk "${arguments[@]-}"
D)使用Bash而不是awk
实现数据文件的解析,并使用配置文件指定输出而无需扩展任何内容(例如,通过指定要打印的字段)用空格分隔。)
前三种方法涉及某种形式的外部数据解释为代码,如果用作输入的文件不能保证安全,则会带来风险。在这方面,方法C可能被认为更好一些,但由于您调用的命令是awk
,因此实际程序将传递给awk
,因此无论awk
能做什么,攻击者都可以(或粗心的用户)对您的文件具有写入权限可能会导致您的脚本执行awk
可以执行的任何操作。