如何更新文本行的某些位置(Bash 中的子字符串)

嗨,我是 shell 编程新手,我面临以下问题,我正在合并两个文件,所以我需要更新表示新文件中行数的位置的页脚,原始页脚看起来如下:

90000000000100000000000012345...n
90000000000300000000000012345...n

行数表示在位置 2 到 13 E.g.

9[000000000010]0000000000012345...n
9[000000000030]0000000000012345...n

我正在使用以下说明

newfooter=`sed 1d $newfile | awk -v completeline=$originalfooter'{total_lines+=1}END{printf "%1d%012d%d\n",substr(completeline,1,1),total_lines,14)}'`

但我的结果如下:

90000000000412345...n

如您所见,一旦 000000000010 + 000000000030 = 000000000040,总行数的总和是可以的,但是行中接下来的 11 个位置丢失了,结果我是尝试获取应该如下:

90000000000400000000000012345...n

老实说,我完全迷失了,感谢您的帮助

dashewan333 回答:如何更新文本行的某些位置(Bash 中的子字符串)

我认为您遗漏了 printf 的最后一部分中的零填充。

尝试更改您的 printf "%1d%012d%d\n" 通过 printf "%1d%012d%017d\n"

这应该告诉 printf 代码您想要最后一个数字的 17 位数字,如果数字小于这 17 位数字,则在左侧填充零。

,

上面似乎很接近(确切?)但我认为这也有效:

Mac_3.2.57$newfooter=`cat newfile | awk -v completeline=$originalfooter '{total_lines+=1}; END {printf("%s%012.12d%s\n",substr(completeline,1,1),total_lines,14))}'`
Mac_3.2.57$echo $newfooter
90000000000300000000000012345...n
Mac_3.2.57$cat newfile | wc -l
      30
Mac_3.2.57$
,

sed 可能是更好的操作字符串的工具

originalfooter='90000000000300000000000012345...n'
# format number
num=$(printf "%012d" 57)
# replace in original footer
echo "$originalfooter" | sed -re "s/([0-9])[0-9]{12}(.*)/\1$num\2/" 

# result: 90000000000570000000000012345...n

有点不同的方法

originalfooter='90000000000300000000000012345...n'
num=$(printf "%012d" 57)
newFooter=$(sed -re "s/([0-9])[0-9]{12}(.*)/\1$num\2/" <<< "$originalfooter")
echo "$newFooter"
,

虽然其他人建议将 %d 更改为 %012d(或 %017d),但问题要简单一些。

考虑以下事项:

awk -v x='000001' 'BEGIN{printf "%d",x}'
1                                          # leading zeros are dropped

awk -v x='000001' 'BEGIN{printf "%06d",x}'
000001                                     # leading zeros are dropped and then added back

这些示例 (%d / %06d) 告诉 printf 将参数视为整数/数字。

正如 OP 在评论中提到的,真正需要的是保留构成“其余部分”的任何内容。

我们可以通过将 %d 换成 %s 来实现这一点,printf 告诉 awk -v x='000001' 'BEGIN{printf "%s",x}' 000001 # string is printed as is,no dropping/adding of 0's 它正在处理一个字符串:

printf "%1d%012d%s\n" ...

这意味着 OP 应该能够通过以下方式获得所需的输出:

%1d

事实上,前导 %s 也可以替换为 printf "%s%012d%s\n" ...

%s

注意:%d 用于未更改的“页脚”部分意味着将保留非数字(如果它们可能存在)而不是导致使用 awk

时出现问题和/或被丢弃

将 OP 的 $ x='90000000000100000000000012345...n' # current printf format: $ awk -v x="${x}" 'BEGIN{printf "%1d%012d%d\n",substr(x,"40",14)}' 900000000004012345 # proposed printf format: $ awk -v x="${x}" 'BEGIN{printf "%s%012d%s\n",14)}' 90000000000400000000000012345...n 代码缩减为演示:

sku
本文链接:https://www.f2er.com/13020.html

大家都在问