Bash 尝试运行文件中存储的几个awk命令
我有一个包含以下命令的文件Bash 尝试运行文件中存储的几个awk命令,bash,shell,Bash,Shell,我有一个包含以下命令的文件 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 /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.
您没有按预期正确执行该命令。由于您正在逐行读取文件(未知原因),您可以直接调用解释器,如下所示
#!/bin/bash
# ^^^^ for running under 'bash' shell
while IFS= read -r line
do
printf "%s" "$line" | bash
done <file
就这样吧
同样要使用awk
,只需对每一行执行以下操作,以避免无用的cat
awk -F "\\t" '{print $21$19$23$15}' file1_name.tsv
您希望管道(
|
)符号按您习惯的方式工作,但实际情况并非如此。要帮助您理解,请尝试以下操作:
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)将参数放入文件中
并对其进行解析,避免使用eval
,例如:
# Assumes arguments separated by spaces
IFS=" " read -r -a arguments;
awk "${arguments[@]-}"
D)在Bash而不是awk
中解析数据文件,并使用配置文件指定输出,而无需展开任何内容(例如,通过指定要打印的字段以空格分隔)
前三种方法涉及以某种形式将外部数据解释为代码,如果无法保证用作输入的文件的安全性,则会带来风险。在这方面,方法C可能会被认为更好一些,但由于您调用的命令是
awk
,实际的程序被传递到awk
,因此无论awk
能做什么,攻击者(或粗心的用户)都可以通过对文件的写访问,您的脚本可以执行awk所能执行的任何操作。避免无用的cat
,您可以将文件作为bash file
运行,而无需任何循环+逐行读取。
# Assumes arguments separated by spaces
IFS=" " read -r -a arguments;
awk "${arguments[@]-}"