从文件名中提取数字

从文件名中提取数字

我有一个遵循此模型的文件名:

 1.raw_bank_details_211.trg
 2.raw_bank_details_222.trg

我需要cut在unix中使用命令并剪切上面的字符串以从字符串中获取211 and并回显该值。222

我已经使用过 grep grep -o -E '[0-9]+',我需要一个替代方案。

答案1

您最好使用标准文本处理工具,而不是像cut.

以下是一些方法:


使用awk,获取_.分隔倒数第二个字段:

awk -F '[_.]' '{print $(NF-1)}' file.txt

grep与 PCRE ( -P):

grep -Po '\d+(?=[^_]*$)' file.txt
  • -o只获取匹配的部分

  • \d+匹配一位或多位数字

  • 零宽度正前瞻,(?=[^_]*$)确保没有_后续直到行尾


sed

sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
  • .*_匹配最后的所有内容_

  • ([[:digit:]]+)匹配所需的数字并放入捕获组中

  • .*与其余的相匹配

  • 在替换中,仅\1使用捕获的组 ,


对于perl,与以下逻辑相同sed

perl -pe 's/.*_(\d+).*/$1/' file.txt 

如果必须使用cut,请分两步进行,首先获取_分隔的第四个字段,然后获取.分隔的第一个字段:

cut -d_ -f4 file.txt | cut -d. -f1

不建议这样做,因为这需要对字段编号进行硬编码。


如果它是一个字符串,我会使用 shell 参数扩展来完成:

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

% echo "${str%%.*}"
211

您仍然可以使用while构造并将每一行放入一个变量中并执行此操作,但这对于大文件来说会很慢。另外,如果需要,您也可以使用_.asIFS并获取硬编码字段(如)。cut


例子:

% cat file.txt                          
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg

% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222

% grep -Po '\d+(?=[^_]*$)' file.txt         
211
222

% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222

% perl -pe 's/.*_(\d+).*/$1/' file.txt 
211
222

% cut -d_ -f4 file.txt | cut -d. -f1
211
222

答案2

cut是错误的工具。要操作短字符串(例如文件名),请尽可能使用 shell 的字符串操作工具。所有 sh 类型的 shell 1(sh、dash、bash、ksh、zsh 等)都有一些基本的字符串操作作为变量替换的一部分。参见例如仪表板手册在“参数扩展”下。您可以删除与模式匹配的最短/最长前缀/后缀。

您需要文件名中的最后一个数字序列,因此:

  1. 通过删除最后一位数字之前的所有内容来确定非数字后缀。
  2. 删除该后缀。
  3. 将所有内容删除到最后一个非数字。
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"

¹除了一些 POSIX 之前的 Bourne shell,但您不关心这些。

相关内容