我有一个遵循此模型的文件名:
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 等)都有一些基本的字符串操作作为变量替换的一部分。参见例如仪表板手册在“参数扩展”下。您可以删除与模式匹配的最短/最长前缀/后缀。
您需要文件名中的最后一个数字序列,因此:
- 通过删除最后一位数字之前的所有内容来确定非数字后缀。
- 删除该后缀。
- 将所有内容删除到最后一个非数字。
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"
¹除了一些 POSIX 之前的 Bourne shell,但您不关心这些。