如果使用bash的起始数字是000,如何将文件中的数字增加1



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 $1 }')

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 ...

我知道必须有一个更干净的方法来处理这个问题。

要增加存储在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(

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

您可以通过使用文件锁定来防止此问题。根据flock手册页,您可以在代码前面加上以下内容:

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

将所有这些放在一起会产生类似于:

#!/bin/bash
nFile="counter.txt"
[[ $FLOCKER != $nFile ]] && 
exec env FLOCKER="$nFile" flock -e "$nFile" "$0" "$@" || :
# 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"

根据你想如何使用数字,最好重新考虑你的程序,这样锁定只发生在所谓的";临界截面";,而不是像这里那样围绕整个程序。

这可能会满足您的需要。

#!/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中,这个perl1-liner将其更改为001,并在每次执行时继续递增1。

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

Perl在所有linux安装中都可用。既然您无论如何都在使用awk,那么不妨使用perl来做一些它非常适合做的事情

最新更新