awk中sprintf生成空字符串致文件无法打开问题求助
问题排查:Shell脚本中sprintf生成空路径导致awk报错
执行的Shell脚本
!ls data/kapitel*.txt \ | while read file; do \ dirname="${file%.*}"; \ mkdir -p "$dirname"; \ awk \ -v dir="$dirname" \ ' /^Artikel$/ { if (f) close(f); f = sprintf("data/kapitel1/Artikel%d.txt", ++n) } { print >> f } ' \ "$file"; \ echo "Writing to file: $f"; \ echo "Creating directory: $dirname"; \ done
报错输出
Writing to file: Creating directory: data/kapitel10 awk: cannot open "" for output (No such file or directory) Writing to file: Creating directory: data/kapitel11 awk: cannot open "" for output (No such file or directory) Writing to file: ...
问题背景
当前目录下有kapitel1.txt到kapitel11.txt多个文件,文件内包含以“Artikel”开头的行。需求是为每个kapitel*.txt文件创建对应名称的目录,将每个kapitel.txt文件按“Artikel”行分割,把分割后的内容保存到对应目录中。
排查与修复建议
- 初始化awk内部变量
n:当前脚本中n未初始化,第一次执行++n时会因变量未定义导致生成的路径缺失数字,甚至为空。在awk脚本的BEGIN块中添加初始化:BEGIN { n = 0 } /^Artikel$/ { if (f) close(f); f = sprintf("%s/Artikel%d.txt", dir, ++n) } - 替换硬编码路径为传入的
dir变量:你当前硬编码了data/kapitel1/,这不符合每个kapitel对应独立目录的需求,改用传入的dir变量生成路径,确保每个文件分割后存入对应目录。 - 避免未初始化
f时执行写入:如果文件开头没有匹配^Artikel$的行,f变量会未赋值,执行print >> f就会报错。可以添加判断逻辑:{ if (f) print >> f } - 添加调试输出验证路径生成:在awk中添加调试语句,查看生成的路径是否正确,比如在设置
f后输出到标准错误:/^Artikel$/ { if (f) close(f); f = sprintf("%s/Artikel%d.txt", dir, ++n) print "Generated path:", f > "/dev/stderr" } - 忽略Shell中
echo $f的无效输出:Shell变量f和awk内部的f是两个独立变量,所以你看到的Writing to file:是空的,这是正常的,无需纠结这个输出,重点解决awk的路径问题。
内容的提问来源于stack exchange,提问作者Leon Preuße
相关产品推荐
相关产品推荐

