Shell
從文件名中提取數字
我有一個遵循此模型的文件名:
1.raw_bank_details_211.trg 2.raw_bank_details_222.trg
我需要
cut
在 unix 中使用命令並剪切上面的字元串以從字元串中獲取211
並222
回顯該值。我已經使用了 grep
grep -o -E '[0-9]+'
,我需要一個替代方法。
cut
是錯誤的工具。要操作短字元串(例如文件名),請盡可能使用 shell 的字元串操作工具。所有 sh 類型的 shell¹(sh、dash、bash、ksh、zsh、…)都有一些基本的字元串操作作為變數替換的一部分。參見例如“參數擴展”下的儀表板手冊。您可以刪除與模式匹配的最短/最長前綴/後綴。您需要文件名中的最後一個數字序列,因此:
- 通過將所有內容剝離到最後一位來確定非數字後綴。
- 刪除該後綴。
- 剝離所有內容,直到最後一個非數字。
filename=1.raw_bank_details_211.trg suffix="${filename##*[0-9]}" number="${filename%"$suffix"}" number="${number##*[!-0-9]}"
¹除了一些 pre-POSIX Bourne shell,但您並不關心這些。
您最好使用標準的文本處理工具,而不是像
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
,請分兩步進行,首先獲取_
分離的第 4 個欄位,然後獲取.
分離的第一個欄位:cut -d_ -f4 file.txt | cut -d. -f1
不建議這樣做,因為這需要對欄位編號進行硬編碼。
如果它是一個字元串,我會使用 shell 參數擴展:
% str='1.raw_bank_details_211.trg' % str=${str##*_} % echo "${str%%.*}" 211
您仍然可以使用
while
構造並將每一行放入變數並執行此操作,但這對於大文件來說會很慢。或者,如果需要,您也可以將_.
其用作IFS
並獲取硬編碼欄位(如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