简体   繁体   English

BASH:使用纯 bash 从变量中删除前导零和尾随零

[英]BASH: Remove leading and trailing zeroes from variable using pure bash

Case Scenerio:案例场景:

Variable or Array
var=( 002.20 20.020 20.002000 00200 20.02 .020)
for f in ${var[@]}; do echo ${f}; done
Output: 2.2 20.02 20.002 200 20.02 .02

Trying to achive this using pure bash that with help of $BASH_REMATCH capture groups尝试使用纯 bash 在 $BASH_REMATCH 捕获组的帮助下实现这一目标

Tried: 
eg. 
f=20.0000210
[[ $f =~ ([0-9]?\.?0?[1-9]?)(0*$) ]]
echo ${BASH_REMATCH[@]}
210 21 0


Expected:
echo ${BASH_REMATCH[@]
20.000021 0

Can anyone help with this.有人能帮忙吗。 Please.请。 After debugging it seems bash capture groups are behaving unusually.调试后似乎 bash 捕获组表现异常。 I dont know how BASH_REMATCH works but from online tutorials i have seen that using () we can split string into BASH_REMATCH array.我不知道 BASH_REMATCH 是如何工作的,但是从在线教程中我看到使用 () 我们可以将字符串拆分为 BASH_REMATCH 数组。 But something odd with splitting但是分裂有些奇怪

oK after some debugging it appears unusual behaviour is due to cygwin bash.好的,经过一些调试,出现异常行为是由于 cygwin bash。 eg var=0002;例如 var=0002; echo ${var##0} or echo ${var##+(0)} doesnt work as expected echo ${var##0} 或 echo ${var##+(0)} 没有按预期工作

Another way: (Another Use Case: Below Method will help splitting a string based on delimeter)另一种方式:(另一个用例:下面的方法将有助于根据分隔符拆分字符串)

var=( 002.20 20.020 20.002000 00200 20.02 .020)
for f in ${var[@]}; do 
[[ $f =~ (^[^\.?]*.)(.*) ]]; 
INT=$(echo ${BASH_REMATCH[1]}); 
FRAC=$(echo ${BASH_REMATCH[2]}); 
echo "$f --> ${INT##+(0)}${FRAC%%+(0)}"; done
Output
002.20 --> 2.2
20.020 --> 20.02
20.002000 --> 20.002
00200 --> 200
20.02 --> 20.02
.020 --> .02

Splits and captures the Integer part and Fractional Part拆分并捕获 Integer 部分和小数部分

Capture 1 - (^[^.?] .) --> Matches beginning to decimal point which is optional in case of natural numbers and append "." Capture 1 - (^[^.?] .) --> 匹配从小数点开始,对于自然数和 append "." 是可选的。 to result导致
Capture 2 - (. ) --> Fractional part捕获 2 - (. ) --> 小数部分

Using BASH_REMATCH[1] & [2], stores integer in INT and Fraction in FRAC使用 BASH_REMATCH[1] 和 [2],将 integer 存储在 INT 中,将 Fraction 存储在FRAC

Using string expansion remove leading "0" from INT and trailing "0" from FRAC使用字符串扩展从 INT 中删除前导“0”,从 FRAC 中删除尾随“0”

If you want to use [[ var =~ REGEX ]] and then BASH_REMATCH , you can do:如果你想使用[[ var =~ REGEX ]]然后BASH_REMATCH ,你可以这样做:

#!/bin/bash

var=( 002.20 20.020 20.002000 00200 20.02 .020)

for i in "${var[@]}"; do             # loop over each element in array
  if [[ $i =~ "." ]]; then           # does it contain '.'?
    [[ $i =~ ^0*(.*[^0]+)0*$ ]]      # use regex to trim both ends
  else
    [[ $i =~ ^0*([^0]+.*$) ]]        # otherwise trim from front.
  fi
  echo ${BASH_REMATCH[1]}            # output result
done

Example Output示例 Output

2.2
20.02
20.002
200
20.02
.02

You can change echo as needed to output with printf for line control as desired.您可以根据需要将echo更改为 output 和printf以根据需要进行线路控制。

$ shopt -s extglob
$ var=( 002.20 20.020 20.002000 00200 20.02 .020 )
$ for f in "${var[@]##+(0)}"; do
    [[ "$f" =~ \. ]] && f="${f%%+(0)}"
    printf '%s\n' "$f"
  done
2.2
20.02
20.002
200
20.02
.02

Using a regular expression approach in bash:在 bash 中使用正则表达式方法:

var=(002.20 20.020 20.002000 00200 20.02 .020 20.0000210)

# regex may match an empty string also
re='^0*([1-9][0-9]*)?(\.[0-9]*[1-9])?0*$'
for n in "${var[@]}"; do
   [[ $n =~ $re ]] && echo "$n => ${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
done

Output: Output:

002.20 => 2.2
20.020 => 20.02
20.002000 => 20.002
00200 => 200
20.02 => 20.02
.020 => .02
20.0000210 => 20.000021

RegEx Demo and Details正则表达式演示和详细信息

RegEx Details:正则表达式详细信息:

  • ^ : Start ^ : 开始
  • 0* : Match 0 or more zeroes 0* : 匹配 0 个或多个零
  • ([1-9][0-9]*)? : Capture group #1 (optional) to match digit 1-9 followed by 0 or more of any digits :捕获组 #1(可选)以匹配数字 1-9,后跟 0 个或多个任意数字
  • (\.[0-9]*[1-9])? : Capture group #2 (optional) to match dot then 0 or more of any digits then digit 1-9 :捕获组 #2(可选)以匹配点,然后是 0 个或多个任何数字,然后是数字 1-9
  • 0* : Match 0 or more zeroes 0* : 匹配 0 个或多个零
  • $ : End $ : 结束
  • In substitution we only keep values captured in capture group #1 and #2 ignoring leading and trailing zeroes.作为替代,我们只保留捕获组#1 和#2 中捕获的值,忽略前导零和尾随零。

You can do it via sed.您可以通过 sed 进行操作。

$ var=( 002.20 20.020 20.002000 00200 20.02 .020)
$ for f in ${var[@]}; do echo $(echo $f|sed -r 's/^0+|0+$//g'); done
2.2
20.02
20.002
2
20.02
.02

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM