Bash:如何提取以 _ 开头和后跟的数字
Bash: How to extract numbers preceded by _ and followed by
我的文件名格式如下:filename_1234.svg
如何检索前面有下划线、后面有点的数字。 .svg
之前可以有一到四个数字
我试过:
width=${fileName//[^0-9]/}
但如果文件名也包含数字,它将 return 文件名中的所有数字,例如
file6name_1234.svg
我找到了两个下划线的解决方案(并将其拆分为一个数组),但我正在寻找一种方法来检查下划线和点。
试试下面的代码:
filename="filename_6_1234.svg"
if [[ "$filename" =~ ^(.*)_([^.]*)\..*$ ]];
then
echo "${BASH_REMATCH[0]}" #will display 'filename_6_1234.svg'
echo "${BASH_REMATCH[1]}" #will display 'filename_6'
echo "${BASH_REMATCH[2]}" #will display '1234'
fi
解释:
=~
: bash 用于正则表达式比较的运算符
^(.*)_([^.])\..*$
:我们寻找任何字符,然后是下划线,然后是任何字符,然后是点和扩展名。我们创建 2 个捕获组,一个用于最后一个下划线之前,一个用于 after
BASH_REMATCH
: 包含捕获组的数组
我会用
sed 's!_! !g' | awk '{print "_" $NF}'
从 filename_1234.svg 到 _1234.svg 然后
sed 's!svg!!g'
删除扩展名。
多一条路
[akshay@localhost tmp]$ filename=file1b2aname_1234.svg
[akshay@localhost tmp]$ after=${filename##*_}
[akshay@localhost tmp]$ echo ${after//[^0-9]}
1234
使用awk
[akshay@localhost tmp]$ awk -F'[_.]' '{print }' <<< "$filename"
1234
如果你设置IFS
,你可以使用Bash的内置read
。
这将通过下划线和点分割文件名并将结果存储在数组 a
.
IFS='_.' read -a a <<<'file1b2aname_1234.svg'
这从数组中取出倒数第二个元素。
echo ${a[-2]}
您可以使用简单的参数扩展并删除子字符串 来简单地从右边 到 trim 直到并包括, '.'
,然后 trim 从 左边 到 '_'
,包括 '_'
,留下你想要的数字,例如
$ width=filename_1234.svg; val="${width%.*}"; val="${val##*_}"; echo $val
1234
注:#
trim从左到首次出现 而 ##
trim 到 最后一次出现 。 %
和 %%
从 右侧 开始的工作方式相同。
解释:
width=filename_1234.svg
- width
保存你的文件名
val="${width%.*}"
- val
持有 filename_1234
val="${val##*_}"
- 最后 val
成立 1234
当然,如果您的意图是 width
应该保持宽度,则不需要使用像 val
这样的临时值。我只是使用临时文件来防止更改 width
的原始内容。如果你想要width
中的结果数,只需将上面各处的val
替换为width
并直接在width
.
上操作即可
注 2: 使用 shell 功能,如 参数扩展 可防止创建单独的子 shell 和生成使用 sed
、grep
或 awk
(或任何不属于 shell 的实用程序时发生的单独过程)。
有一个使用 cut 的解决方案:
name="file6name_1234.svg"
num=$(echo "$name" | cut -d '_' -f 2 | cut -d '.' -f 1)
echo "$num"
-d
用于指定分隔符。
-f
指的是想要的字段。
我对性能一无所知,但它易于理解和维护。
我的文件名格式如下:filename_1234.svg
如何检索前面有下划线、后面有点的数字。 .svg
我试过:
width=${fileName//[^0-9]/}
但如果文件名也包含数字,它将 return 文件名中的所有数字,例如
file6name_1234.svg
我找到了两个下划线的解决方案(并将其拆分为一个数组),但我正在寻找一种方法来检查下划线和点。
试试下面的代码:
filename="filename_6_1234.svg"
if [[ "$filename" =~ ^(.*)_([^.]*)\..*$ ]];
then
echo "${BASH_REMATCH[0]}" #will display 'filename_6_1234.svg'
echo "${BASH_REMATCH[1]}" #will display 'filename_6'
echo "${BASH_REMATCH[2]}" #will display '1234'
fi
解释:
=~
: bash 用于正则表达式比较的运算符^(.*)_([^.])\..*$
:我们寻找任何字符,然后是下划线,然后是任何字符,然后是点和扩展名。我们创建 2 个捕获组,一个用于最后一个下划线之前,一个用于 afterBASH_REMATCH
: 包含捕获组的数组
我会用
sed 's!_! !g' | awk '{print "_" $NF}'
从 filename_1234.svg 到 _1234.svg 然后
sed 's!svg!!g'
删除扩展名。
多一条路
[akshay@localhost tmp]$ filename=file1b2aname_1234.svg
[akshay@localhost tmp]$ after=${filename##*_}
[akshay@localhost tmp]$ echo ${after//[^0-9]}
1234
使用awk
[akshay@localhost tmp]$ awk -F'[_.]' '{print }' <<< "$filename"
1234
如果你设置IFS
,你可以使用Bash的内置read
。
这将通过下划线和点分割文件名并将结果存储在数组 a
.
IFS='_.' read -a a <<<'file1b2aname_1234.svg'
这从数组中取出倒数第二个元素。
echo ${a[-2]}
您可以使用简单的参数扩展并删除子字符串 来简单地从右边 到 trim 直到并包括, '.'
,然后 trim 从 左边 到 '_'
,包括 '_'
,留下你想要的数字,例如
$ width=filename_1234.svg; val="${width%.*}"; val="${val##*_}"; echo $val
1234
注:#
trim从左到首次出现 而 ##
trim 到 最后一次出现 。 %
和 %%
从 右侧 开始的工作方式相同。
解释:
width=filename_1234.svg
-width
保存你的文件名val="${width%.*}"
-val
持有filename_1234
val="${val##*_}"
- 最后val
成立1234
当然,如果您的意图是 width
应该保持宽度,则不需要使用像 val
这样的临时值。我只是使用临时文件来防止更改 width
的原始内容。如果你想要width
中的结果数,只需将上面各处的val
替换为width
并直接在width
.
注 2: 使用 shell 功能,如 参数扩展 可防止创建单独的子 shell 和生成使用 sed
、grep
或 awk
(或任何不属于 shell 的实用程序时发生的单独过程)。
有一个使用 cut 的解决方案:
name="file6name_1234.svg"
num=$(echo "$name" | cut -d '_' -f 2 | cut -d '.' -f 1)
echo "$num"
-d
用于指定分隔符。
-f
指的是想要的字段。
我对性能一无所知,但它易于理解和维护。