2017-02-24 59 views
1

我有一个文件,下面的命令试图运行存储在文件中几个AWK命令

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. 
+2

避免无用的'猫',你可以运行该文件作为'bash文件'没有任何循环+阅读逐行。 – anubhava

回答

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 
+0

bash 做了伎俩 – tempuser

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)实施猛砸,而不是awk数据文件的解析,并使用你的配置文件来指定输出而不需要扩展任何东西(例如指定要用空格分隔的字段来打印)。

前三种方法涉及某种形式的外部数据解释代码,如果用作输入的文件无法保证安全,则会带来风险。方法C在这方面可能会被认为更好一些,但是由于您要拨打的命令是awk,因此实际的程序会传递到awk,因此无论awk能做什么,攻击者(或粗心的用户)都可以对您的文件进行写入访问导致你的脚本可以做任何事情awk可以做。