awk使用shell参数或shell变量将输出打印到目录

时间:2017-06-15 23:57:42

标签: bash shell awk text-processing

如何使用shell参数或命令参数将输出打印到awk中的目录?

Shell程序调用并将参数传递给awk程序:

testshell.sh

shelloutputdir="./ouputdir/"
./testawk inputfile.txt ./outputdir/

Awk计划:

testawk

#!/usr/bin/awk -f
{
    print FILENAME > "./outputdir/outputfile1.txt"
    fn2="outputfile2.txt"
    fn3="outputfile3.txt"
    fn4="outputfile4.txt"
    print FILENAME > ARGV[2]"/"fn2
    print FILENAME > ARGV[2]"subdir/"fn3
    print FILENAME > $shelloutputdir"subdir/"fn4
}

注意:

inputfile.txt

只是一个例子,因为shell和awk程序将处理其他参数。

输出目录已存在。

./outputdir/
./outputdir/subdir/

输出:

./outputdir/outputfile1.txt
./outputdir/outputfile2.txt
./outputdir/subdir/outputfile3.txt

outputfile4.txt未创建

错误:

awk: ./testawk:9: (FILENAME=inputfile.txt FNR=1) fatal: can't redirect to `input text filesubdir/outputfile4.txt' (No such file or directory)

问题摘要:

  1. 如何在awk中显式设置输出目录?

  2. 如何使用命令行参数在awk中设置输出目录?

  3. 如果目录在awk中不存在,如何创建目录?

  4. 如何将shell变量传递给awk变量来设置输出目录?

  5. 感谢帮助和任何示例方法

2 个答案:

答案 0 :(得分:2)

使用shebang执行awk脚本只会让你的生活更加艰难,不要这样做。如果你摆脱了shebang并将“testawk”写成:

odir="$1"
shift
/usr/bin/awk -v odir="$odir" '
{
    print FILENAME > (odir "outputfile1.txt")
    fn2="outputfile2.txt"
    fn3="outputfile3.txt"
    fn4="outputfile4.txt"
    print FILENAME > (odir fn2)
    print FILENAME > (odir "subdir/" fn3)
    print FILENAME > (odir "subdir/" fn4)
}
' "$@"

然后你可以把它称为:

shelloutputdir="./outputdir/"
./testawk "$shelloutputdir" inputfile.txt

或做任何你喜欢的事情。关键是不使用shebang可以让awk从shell args和awk文件名中分离awk变量的初始值。

您可以使用

创建一个名称存储在变量foo中的目录
system("mkdir -p \047" foo "\047")

答案 1 :(得分:1)

注意:
*此答案基于使用 shebang line awk)的独立#!/usr/bin/awk -f脚本来解决所提问题。
* Ed Morton's helpful answer显示如何从shell脚本中调用awk作为替代方案,这有其优势。

脚本操作数之后传递给awk的所有操作数(在本例中隐含为独立脚本本身)默认情况下解释为输入文件

鉴于./outputdir/定义为目录,它不能作为输入文件,这就是您收到警告的原因。

然而, Awk提供伪文件名操作数语法 <var>=<value> ,而不是传递文件名定义一个Awk 变量 ,类似于预脚本 -v <var>=<value> 选项语法(并且假设您的通过shebang行调用,-v - 基于选项的变量赋值是不是选项)。

请注意,这些分配在脚本操作数列表中遇到时会发生,因此您需要放在实际输入文件之前其处理依赖于它们

shelloutputdir="./outputdir/"
./testawk odir="$shelloutputdir" inputfile.txt # Note the definition of variable `odir`

您可以通过这种方式定义变量的数量没有限制,但是,至少假设您受到命令行的最大总长度的限制,该值接近但小于getconf ARG_MAX报告的内容。

以上定义了Awk变量odir,因此您的脚本需要引用它:

#!/usr/bin/awk -f
{
    fn3="outputfile3.txt"
    print FILENAME > (odir "subdir/" fn3)
}

正如Ed Morton所指出的,如果输出文件名是从表达式计算出来的,那么表达式应该包含在(...) 中坚固;虽然它可能在一些 Awk实现(例如,GNU Awk和Mawk)中没有括号的情况下工作,但它会破坏其他(例如,BSD / macOS Awk)。 在这种情况下,Awk POSIX spec不会规范行为。

  
      
  1. 如何在awk中明确设置输出目录?
  2.   

没有Awk内部机制,但您可以使用 shell cd预先输出目录

  
      
  1. 如何使用命令行参数在awk中设置输出目录?
  2.   

见上面的解决方案。 Awk中没有特殊的output-directory参数,但您可以将输出目录路径作为Awk 变量传递。

  
      
  1. 如果目录在awk中不存在,如何创建目录?
  2.   

没有Awk内部机制,但是 - 如果创建目录。在shell中提前不是一个选项 - 您可以使用system()函数来调用mkdir; e.g:

# If the dir. name never contains ' (single quotes):
awk -v odir="out-dir" 'BEGIN { system("mkdir \047" odir "\047") }'

# *From inside your stand-alone Awk script only*, you don't need \047 to represent
# ' chars - see below.
system("mkdir '" odir "'")

# Otherwise, more work is needed:
awk -v odir="out'dir" '
   function shellQuote(s) { gsub("\047", "\047\\\047\047", s); return "\047" s "\047" }
   BEGIN { system("mkdir " shellQuote(odir)) }
'

\047是表示'的八进制转义序列,从shell 明确调用awk时必须使用,因为'...'已被用于整合脚本,这会阻止使用嵌入式 '字符。总而言之,因为单引号shell字符串不支持它。

这是一个方面,其中独立 awk脚本优于shell的显式awk调用:您可以自由使用文字{{ 1}}独立脚本中的实例 - 不需要'

  
      
  1. 如何将shell变量传递给awk变量以设置输出目录?
  2.   

见问题#2的答案。