如何使用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)
问题摘要:
如何在awk中显式设置输出目录?
如何使用命令行参数在awk中设置输出目录?
如果目录在awk中不存在,如何创建目录?
如何将shell变量传递给awk变量来设置输出目录?
感谢帮助和任何示例方法
答案 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不会规范行为。
- 如何在awk中明确设置输出目录?
醇>
没有Awk内部机制,但您可以使用 shell 到cd
预先输出目录 。
- 如何使用命令行参数在awk中设置输出目录?
醇>
见上面的解决方案。 Awk中没有特殊的output-directory参数,但您可以将输出目录路径作为Awk 变量传递。
- 如果目录在awk中不存在,如何创建目录?
醇>
没有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}}独立脚本中的实例 - 不需要'
。
- 如何将shell变量传递给awk变量以设置输出目录?
醇>
见问题#2的答案。