用增量替换文件中行中的文本

用增量替换文件中行中的文本

我有一个包含多行的文件(行数未知)

DD0TRANSID000019021210504250003379433005533665506656000008587201902070168304000.0AK  0000L00000.00  N          01683016832019021220190212N0000.001683065570067.000000.00000.0000000000000NAcknowledgment                                                                                                                                        
DD0TRANSID000019021210505110003379433005535567606656000008587201902085381804000.0FC  0000L00000.00  N          53818538182019021220190212N0000.053818065570067.000000.00000.0000000000000NFirst Contact                                                                                                                                         
DD0TRANSID000019021210510360003379433005535568006656000008587201902085381804000.0SR  0000L00000.00  N          53818538182019021220190212N0000.0

文本 TRANSID000 位于从第 3 到第 10 位置开始的每一行中,我需要能够以 1 的增量将其替换为 TRAN000066

66 是我从另一个文件(例如 nextcounter)获取的变量,用于存储计数器的开始。一旦程序更新了所有行,我应该能够捕获最后一个数字并用它更新下一个计数器文件。

输出

DD0TRAN00066019021210504250003379433005533665506656000008587201902070168304000.0AK  0000L00000.00  N          01683016832019021220190212N0000.001683065570067.000000.00000.0000000000000NAcknowledgment                                                                                                                                        
    DD0TRAN00067019021210505110003379433005535567606656000008587201902085381804000.0FC  0000L00000.00  N          53818538182019021220190212N0000.053818065570067.000000.00000.0000000000000NFirst Contact                                                                                                                                         
    DD0TRAN00068019021210510360003379433005535568006656000008587201902085381804000.0SR  0000L00000.00  N          53818538182019021220190212N0000.053818065570067.000000.00000.0000000000000NStatus Report                                                                                                                                         

答案1

perl

perl -spe 's/TRANSID000\K/$n++/e' -- -n=66 < your-file

或者,如果您需要用 0 填充数字,使其长度为 5(00001、00010、00100...):

perl -spe 's/TRANSID\K000/sprintf "%05d", $n++/e' -- -n=66 < your-file

答案2

我认为这个awk脚本应该可以完成这项工作。它在脚本内完成所有操作,因为这是最简单的设置。但请进一步了解另一种方法,它可以让您将 nextcounter 作为 shell 变量进行处理:

BEGIN
    { getline counter < "nextcounter"; }
/TRANSID000/
    {
      replacement_string = sprintf("TRAN%05d", counter++);
      gsub("TRANSID000", replacement_string);
      print;
    }
END
    { printf("%d\n", counter) > "nextcounter"; }

您可以使用这样的单行代码来调用它:

cat data | awk -- 'BEGIN { getline counter < "nextcounter"; } /TRANSID000/{ replacement_string = sprintf("TRAN%05d", counter++); gsub("TRANSID000", replacement_string); print; } END { printf("%d\n", counter) > "nextcounter"; }'

请注意:

  • 在你的OP中,你首先说你想要一个像TRAN000066ie这样总共有6位数字的字符串,但是你的示例输出有一个像TRAN00066ie这样有5位数字的字符串。我遵循了您的示例输出,但如果您需要 6 位精度,只需更改字符串TRAN%05d即可TRAN%06d
  • 根据您的描述,我认为从nextcounter文件中获取的数字是第一个用于替换的数字。相反,如果您想首先增加数字,只需将其更改counter++++counter
  • 我认为nextcounter 这是一个仅包含一行且只有一个整数的文件。如果情况并非如此,那么您需要修改脚本的BEGIN 和END部分

如果你更喜欢不是要让 awk 脚本nextcounter直接更新文件,并将此类 nextcounter 值作为 shell 变量处理,您需要更复杂的设置,其中涉及使用临时文件来存储更新的计数器。像这样的东西:

tempfile=$(mktemp) ; cat data | awk -v counter="${nextcounter:-0}" -v tempfile="${tempfile}" -- '/TRANSID000/{ replacement_string = sprintf("TRAN%05d", ++counter); gsub("TRANSID000", replacement_string) ; print; } END { printf("%d\n", counter) > tempfile; }' && read nextcounter < "${tempfile}" ; rm "${tempfile}"

分解解释:

tempfile=$(mktemp) \ # create temporary file
cat data | pipe data to awk ...
    awk -v counter="${nextcounter:-0}" -v tempfile="${tempfile}" -- \ # provide initial counter and tempfile to awk
    '/TRANSID000/ \
        { replacement_string = sprintf("TRAN%05d", ++counter); \
          gsub("TRANSID000", replacement_string) ; \
          print; \
        } \
     END \
        { printf("%d\n", counter) > tempfile; }' \ # write updated counter to temporary file
    && read nextcounter < "${tempfile}" \ # read updated counter into ${nextcounter} shell variable
rm "${tempfile}"

这需要 中的初始计数器${nextcounter},并在最后更新相同的变量。

如果无法创建临时文件,那么您可以尝试在未命名管道上使用文件描述符,但这需要 Bash v3+允许以读/写模式打开管道的系统。 Linux 允许,MacOS 不允许,不知道其他 Unix-es 是否如此。

它会像:

exec 9<> <(:) ; cat data | awk -v counter="${nextcounter:-0}" -- '/TRANSID000/{ replacement_string = sprintf("TRAN%05d", ++counter); gsub("TRANSID000", replacement_string); print; } END { printf("%d\n", counter) > "/dev/fd/9"; }' && read nextcounter <&9 ; exec 9<&-

细分:

exec 9<> <(:) # open fd 9 onto unnamed pipe R/W
cat data | \
    awk -v counter="${nextcounter:-0}" -- \
    '/TRANSID000/ \
         { replacement_string = sprintf("TRAN%05d", ++counter); \
           gsub("TRANSID000", replacement_string); \
           print; } \
      END \
         { printf("%d\n", counter) > "/dev/fd/9"; }' \ # write updated counter to fd 9
    && read nextcounter <&9 # read updated counter from fd 9 into ${nextcounter} shell variable
exec 9<&- # close fd 9

答案3

如果你的文件在 bash shell 类型的“文件”中,

inp=66;i=$inp; while read -r ln;do;echo $ln sed -E "s/TRANSID000/TRAN0000$i/i";let i++;done<file

相关内容