如果起始编号为 000,如何使用 bash 将文件中的编号增加 1?

How to increase the number in a file by 1 if the starting number is 000 using bash?

GNU bash,版本 4.4.20
Ubuntu 18.04.5

我需要在循环中将文件中的数字递增 1。号码必须满足3位数字

示例:

001 + 1 = 002
002 + 1 = 003
003 + 1 = 004
004 + 1 = 005
005 + 1 = 006
006 + 1 = 007
007 + 1 = 008
008 + 1 = 009
009 + 1 = 010
010 + 1 = 011

我一直在每次循环后将文件中的数字加 1。然后我计算文件中的字符数,然后在数字前添加零以满足 3 个字符的数字要求,如下所示:

#!/bin/bash

nFile="counter.txt"

if [ ! -e "$nFile" ]; then
    echo "1" > "$nFile"
    echo "Number is 001"
else
    n=$(cat "$nFile")
    m=$(( n + 1 ))
    echo "$m" > "$nFile"
    cCount=$(wc -c "$nFile" | awk '{ print  }')
    
    if [ "$cCount" = "2" ]; then
        echo "Number is 00${m} ..."
    elif [ "$cCount" = "3" ]; then
        echo "Number is 0${m} ..."
    fi
fi

以上工作正常并满足 shellcheck 先生。每次循环运行时,数字都会像这样正确打印:

Number is 001 ...
Number is 002 ...
Number is 003 ...
Number is 004 ...
Number is 005 ...
Number is 006 ...
Number is 007 ...
Number is 008 ...
Number is 009 ...
Number is 010 ...
Number is 011 ...
Number is 012 ...

我知道必须有更简洁的方法来处理这个问题。

这可能会满足您的要求。

#!/usr/bin/env bash

i=1
file_name=somejazz.txt

while printf -v num '%03d' "$i" && [[ -e "$num-$file_name" ]]; do
  ((i++))
done

> "$num-$file_name"

如果文件不存在则创建名为 001-somejazz.txt 的文件,如果存在则递增 1,依此类推。

Perl 有一个很酷的字符串递增算法。因此,如果 000 在文件 n.txt 中,则此 perl 1-liner 会将其更改为 001 并在每次执行时继续递增 1。

perl -i -e '$n=<>;chomp($n);$n++;print("$n\n")' n.txt

Perl 适用于所有 linux 安装。既然你正在使用 awk,那么不妨使用 perl 来做一些它很适合做的事情。

要增加存储在 bash 变量 x 中的整数,您可以执行类似 ((x=x+1))((++x)).

的操作

但是如果数字可以有前导零,那么你必须更加小心:

x=8
echo $((++x))        # okay, prints 9

x=008
echo $((++x))        # fails with error message

declare -i x=10#008  # force base 10
echo $((++x))        # okay, prints 9

要将整数 y 格式化为固定宽度的 3 位数字,前导零,您可以使用:

printf '%03d' "$y"

您只需确保 y:

  • 是一个整数,
  • 没有前导零(因此 bash 不将其视为八进制),并且
  • 不是999(会溢出到1000

如果您将状态永久存储在进程外的文件中,那么您需要注意不要同时 运行 您的代码的多个副本。如果这样做,因为您的 read/modify/write 过程不是原子的,状态可能会损坏。

您可以使用文件锁定来防止此问题。根据 flock 联机帮助页,您可以在代码前加上类似以下内容的前缀:

[ "${FLOCKER}" != "[=12=]" ] && exec env FLOCKER="[=12=]" flock -en "[=12=]" "[=12=]" "$@" || :

将所有这些放在一起得到类似的东西:

#!/bin/bash

nFile="counter.txt"

[[ $FLOCKER != $nFile ]] && \
exec env FLOCKER="$nFile" flock -e "$nFile" "[=13=]" "$@" || :

# if we tell flock to use $nFile as its lockfile,
# it will create it (empty) if it doesn't already exist
# so we don't need to test for its existence here
read n <"$nFile"

# force input to be treated as base 10
# n is treated as being 0 if empty
# format incremented value with leading zeros and store into m
printf -v m '%03d' $(( 10#$n + 1 ))

echo "Number is $m ..."
echo $m >"$nFile"

根据您想如何使用这些数字,重构您的程序可能会更好,这样锁定只发生在所谓的“关键部分”周围,而不是像此处那样发生在整个程序周围。