Shell

從文件名中提取數字

  • April 25, 2017

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

1.raw_bank_details_211.trg
2.raw_bank_details_222.trg

我需要cut在 unix 中使用命令並剪切上面的字元串以從字元串中獲取211222回顯該值。

我已經使用了 grep grep -o -E '[0-9]+',我需要一個替代方法。

cut是錯誤的工具。要操作短字元串(例如文件名),請盡可能使用 shell 的字元串操作工具。所有 sh 類型的 shell¹(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]}"

¹除了一些 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

引用自:https://unix.stackexchange.com/questions/361205