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[@]-}"