我想编写一个bash脚本,用于从文件名中提取字符串,并将该字符串插入到同一文件中的特定位置。
例如:在/root目录下有不同的日期目录20160201,20160202,20160203,每个目录下有一个文件abc20160201.dat,abc20160202.dat,abc20160203.dat。
我的要求是首先从每个文件名中提取日期,然后将该日期插入到文件中每个记录的第二列中。
用于提取我正在使用的日期
f=abc20160201.dat
s=`echo $f | cut -c 4-11`
echo "$f -> $s"并用于插入iI使用的日期
awk 'BEGIN { OFS = "~"; ORS = "\n" ; date="20160201" ; IFS = "~"} { $1=date"~"$1 ; print } ' file > tempdate但在我的awk命令中,日期位于第一列。请让我知道我做错了什么。
正在对其执行此操作的文件是一个分隔文件,其中的字段由~字符分隔。
或者如果有人对此有更好的解决方案,请告诉我。
发布于 2016-02-23 20:14:06
输入字段分隔符的变量是FS,而不是IFS。因此,输入行根本不会被拆分,因此,当您在字段1之后添加日期时,它会出现在行尾。
您应该能够使用:
f=abc20160201.dat
s=$(echo $f | cut -c 4-11)
awk -v date="$s" 'BEGIN { FS = OFS = "~" } { $1 = $1 OFS date; print }' $f将修改后的输出生成为标准输出。AFAIK,awk没有覆盖选项,所以如果你想要修改文件‘就地’,你需要将脚本的输出写入一个临时文件,然后复制或移动临时文件覆盖原始文件(如果你复制了临时文件,则删除临时文件)。复制同时保留硬链接和符号链接(以及所有者、组、权限);移动则不保留。如果文件名既不是符号链接也不是链接文件,则移动会更简单。(复制总是“有效”的,但复制比移动花费更长的时间,需要删除,而且有一个更长的窗口,而覆盖复制可能会留下一个不完整的文件,如果中断。)
概括一下:
for file in /root/2016????/*.dat
do
tmp=$(mktemp "$(dirname "$file")/tmp.XXXXXX)")
awk -v date="$(basename "$file" | cut -c 4-11)" \
'BEGIN { FS = OFS = "~" } { $1 = $1 OFS date; print }' "$file" >"$tmp"
mv "$tmp" "$file"
done首选$(…)而不是反引号的原因之一是,使用$(…)管理嵌套操作和报价要容易得多。mktemp命令在与源文件相同的目录中创建临时文件;您可以合理地决定改用mktemp "${TMPDIR:-/tmp}/tmp.XXXXXX。更通用的脚本将迭代"$@" (传递给它的参数),但它可能需要验证文件的基本名称是否与您需要的/expect格式匹配。
添加代码以处理中断,或在复制和移动之间进行选择,留给读者作为练习。请注意,该脚本不会尝试检测以前是否在文件上运行过它。如果在同一个文件上运行三次,最终得到的结果是第2-4列都包含日期。
https://stackoverflow.com/questions/35571016
复制相似问题