从文件读取内容后在awk中使用变量的脚本问题排查
解决Bash脚本提取文件名字段的问题
首先,咱们先拆解你脚本里的两个典型问题:
错误1:重定向语法写错了
你第一个awk命令里用了<<<<<"$FILE"——这多打了两个<!正确的Here字符串语法是<<<,用来把变量内容直接作为awk的标准输入。多出来的<会被bash当成文件重定向操作,导致它找不到对应的文件,所以才会抛出/ : No such file or directory的错误。
错误2:awk没正确处理你传递的变量
第二个awk命令你用-v var="${FILE}"传递了文件名变量,但你的awk脚本里根本没用到var!这时候awk会默认从标准输入读取数据——也就是整个zips_not_received.csv文件,所以每次循环它都会输出所有行的第二个字段,导致你看到重复的bar2、bar1。
推荐解决方案:用Bash内置字符串处理(更高效)
没必要每次循环都调用awk(外部进程),Bash本身就有强大的字符串拆分能力,速度更快还减少资源消耗:
#!/bin/bash while read -r FILE; do echo "$FILE" # 提取host:从开头到第一个下划线之前的部分 host="${FILE%%_*}" # 提取fp:先去掉第一个下划线及之前的内容,再取到下一个下划线之前的部分 fp="${FILE#*_}" fp="${fp%%_*}" echo "$host" echo "$fp" done < zips_not_received.csv
语法小解释:
${var%%pattern}:从变量末尾开始删除最长匹配pattern的内容,这里_*匹配第一个下划线及后面所有字符,剩下的就是foop07这类host值。${var#*pattern}:从变量开头删除最短匹配pattern的内容,这里*_匹配第一个下划线及之前的字符,剩下的是bar2_20190423152612.zip,再用%%_*就得到bar2这类fp值。
如果你习惯用awk的修正版本
要是你更倾向于用awk,那得修正输入传递的方式:
#!/bin/bash while read -r FILE; do echo "$FILE" # 用<<<正确把变量内容传给awk host=$(awk 'BEGIN { FS = "_" } { print $1 }' <<< "$FILE") echo "$host" # 同样用<<<传递输入,或者用split处理变量 fp=$(awk 'BEGIN { FS = "_" } { print $2 }' <<< "$FILE") # 另一种用-v传递变量并拆分的写法: # fp=$(awk -v file="$FILE" 'BEGIN { FS="_"; split(file, arr, "_"); print arr[2] }') echo "$fp" done < zips_not_received.csv
这样修改后,就能得到你预期的输出了,之后你就可以在循环里用$host和$fp执行ssh命令获取对应文件啦。
内容的提问来源于stack exchange,提问作者Red_badger
相关产品推荐
相关产品推荐

