【问题标题】:Perl / Awk / Sed - Find and Replace Number & auto-incrementPerl / Awk / Sed - 查找和替换数字和自动增量
【发布时间】:2018-05-30 22:54:32
【问题描述】:

我正在寻找一个 perl/awk/sed 命令来自动增加第 7 列中的数字 文件 knownfile.txt 中的示例行:

该文件具有格式和 7 列。

today is a great day and it
is also an amazing day tomorrow now
blahblah foo today build number is 5928

我想保留所有格式,只需将 5928 替换为 5929 并保存文件

我试过了:

awk '/blahblah/{ $7++; print $0 }' filename > tmp && mv tmp filename

它增加了数字,我认为它保留了格式,但它只将编辑的行打印到文件中。

【问题讨论】:

  • 发布更多的示例输入和预期输出行并格式化。
  • 数字是否总是在同一个地方,即在行尾?
  • 汤姆,是的,我要替换的数字总是在行尾。
  • 仅供参考,您对字段执行的任何操作(例如上面的 $7)都会更改格式,因为更改字段会告诉 awk 使用 OFS 值(默认为单个空格)重新编译记录($0)字段,因此默认情况下,所有连续空白链都将替换为单个空白字符。为避免这种情况,您需要将记录作为一个整体进行操作,而不是记录中的任何 1 个字段。

标签: perl bash awk sed


【解决方案1】:
$ cat file
today is a great day and it
is also an amazing day tomorrow now
blahblah    foo   today     build number is     5928

$ awk '{sub(/[[:digit:]]+$/,$NF+1)}1' file
today is a great day and it
is also an amazing day tomorrow now
blahblah    foo   today     build number is     5929

如果这不能满足您的要求,那么请认真考虑您发布的示例输入和预期输出,因为这就是我们要做的全部。

【讨论】:

  • 处理我的格式问题的好方法(或者如果输入不同,受到影响)。我想应该在块之前有/foo/
  • idk,我在 /foo/ 上看到了一些匹配的答案,但我在问题中没有看到任何提及。
  • 好点,这似乎不再是问题的一部分。我想我需要跟上! +1 然后用于保留行格式并完成摘要。
【解决方案2】:

使用 perl 单行代码

perl -i -pe 's/(\d+)$/1+$1/e' knownfile.txt

【讨论】:

  • 我收到消息Modification of a read-only value attempted at -e line 1, <> line 1.
  • 我改成perl -i -pe 's/(\d+)$/1+$1/e' knownfile.txt解决了这个问题
【解决方案3】:

鉴于数字始终位于行尾,您可以在 awk 中执行此操作:

awk '/foo/{++$NF}1' file

其中file 是您要操作的文件。当该行包含单词“foo”时,这只会增加最后一列的值。末尾的1 表示执行默认操作,即打印该行。

要在文件上“就地”执行此操作,您必须跳过几个环节:

awk '/foo/{++$NF}1' file > tmp && mv tmp file

gawk 的较新版本支持就地编辑,但这适用于任何地方。

【讨论】:

  • 与大多数语言一样,awk 有一个++ 运算符,因此您可以写成$NF++++$NF 而不是$NF = $NF+1
  • @Ed 为了提高效率,我将使用预增量版本;) 感谢您指出这一点。我一开始就应该这样做。
  • 实际上,显然,当它保存数据时,它会删除一些格式,这会导致问题。有什么方法可以保持编辑行的间距/格式?
  • @user3642747 它适用于您问题中的示例。如果您的文件不同,您应该编辑问题以使其更清晰。
  • @user3642747 当你像这样增加一个字段时,它会改变格式以使用默认的字段分隔符(一个空格)用于整行。查看 Eds 解决方案,使用sub 更改字段而不更改行的格式。
【解决方案4】:
$ perl -i -pe 's/\d+$/$&+($&>0)/e if /foo/' knownfile.txt

不认为-32 是负面的。

【讨论】:

    【解决方案5】:

    这个脚本没有缺点。

    use Fcntl;
    my $fh;
    open $fh,"+<$ARGV[0]";
    while(<$fh>) {
        if (/foo/) {
            s/(-?\d+)/(($1 > 0) ? ($1+1) : $1)/ge;
        }
        $file .= $_;
    }
    seek($fh, 0, SEEK_SET);
    print $fh $file;
    close $fh;
    

    【讨论】:

    • 有些人可能会争辩说,12 行长的脚本和隐晦的语句是一个缺点:-)。
    猜你喜欢
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 2012-12-30
    • 2021-12-24
    • 2017-11-11
    • 2014-12-04
    • 1970-01-01
    • 2014-07-07
    相关资源
    最近更新 更多