我有很長的列表如下:慶典0鍵盤的數字
D6N T69TN K70R M184V T215FEG
的結果必須是這樣的:
D006N T069TN K070R M184V T215FEG
我在bash中新,我試圖總部設在分裂的方法它在列和重新格式化。然而,第二和第三推定列的位置和長度並不固定。 謝謝你的幫助!
我有很長的列表如下:慶典0鍵盤的數字
D6N T69TN K70R M184V T215FEG
的結果必須是這樣的:
D006N T069TN K070R M184V T215FEG
我在bash中新,我試圖總部設在分裂的方法它在列和重新格式化。然而,第二和第三推定列的位置和長度並不固定。 謝謝你的幫助!
爲此,您可以用awk,使用內置match
功能:
awk 'match($0, /[0-9]+/) { printf "%s%03d%s\n",
substr($0, 0, RSTART - 1), substr($0, RSTART, RLENGTH), substr($0, RSTART + RLENGTH) }' file
當match
是成功的,它設置了兩個變量RSTART
和RLENGTH
,可用於提取子。中間的子字符串使用%03d
進行格式化,以填充前導零。
任何不符合圖案的線都不會被打印。
另一種選擇用perl:
perl -pe 's/\d{1,3}/sprintf("%03d", $&)/eg' file
這取代的一至三個數字的任何序列具有零填充三位數。在這個版本中,所有行都被打印出來。
呵呵,我喜歡perl的一個......用'/ e'聰明的工作:-) – anishsane
的確,perl版本工作的很快很順利!謝謝。 – user3829806
它不再與sed
的正則表達式一點,但在這裏它是在Perl
:
echo "D6N" | perl -pe 's/(\D)(\d)(\D)/${1}0$2$3/g; s/(\D)(\d\d)(\D)/${1}0$2$3/g;'
將墊被非數字環繞零1年和2位數。它用一個簡單的技巧來實現:用一個零填充1位數字(因此1位數字成爲2位數字),然後用另一個零填充2位數字。
AFAIK,對此沒有簡單的純Bash解決方案。因此,我更喜歡Perl,因爲Perl表達式很簡短,並且Perl無處不在。
s='D6N
T69TN
K70R
M184V
T215FEG'
echo "$s" | perl -ne '/^(\D*)(\d{1,2})(\D*)$/m and printf "%s%03s%s", $1, $2, $3 or print'
雖然這個代碼可能回答這個問題,但提供 關於_why_和/或_how_的附加上下文會回答 這個問題會顯着改善它的長期 值。請[編輯]你的答案,添加一些解釋。 –
sed
另一個實施基於:
$ cat testfile
D6N
T69TN
K70R
M184V
T215FEG
$ sed -r 's/[0-9]+/00&/g; s/0?0?([0-9]{3})/\1/g' testfile
D006N
T069TN
K070R
M184V
T215FEG
邏輯:無條件前綴2個0到號碼&移除前導零,直到數爲3位長。
這GNU AWK也可以完成這項工作:
awk -v RS='[0-9]+' 'RT{print $0 sprintf("%03d", RT); next} 1' ORS= file
D006N
T069TN
K070R
M184V
T215FEG
使用bash的正則表達式:
#!/bin/bash
re='([[:alpha:]]*)([[:digit:]]*)([[:alpha:]]*)'
while IFS= read -r line; do
[[ $line =~ $re ]]
printf "%s%03d%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done < infile
這與正則表達式的每一行相匹配,並且抓住了三組:字母,數字,字母。格式字符串printf
可確保數字組的長度小於三位數字時爲零填充。
你如何構建和打印你的「清單」? 「列表」從哪裏來?也許Bash本身不是正確的工具,但awk或sed可能是? –
同意,bash是一個shell,而不是數據處理器,所以使用像awk,sed,grep等其他工具很可能會變得異常 – edhurtig
@ user3829806你的行總是使用'( [AZ] +)([0-9] +)([AZ] +)',你會一直需要填充最大數字的長度......即數字可能超過3位數? – edhurtig