2017-05-31 79 views
1

我有這種奇怪的情況,我得到了一系列表示二進制數據的HEX值。有趣的是,他們是偶爾長度不同,如:BASH:基於最長的字符串填充一系列HEX值

40000001AA 
0000000100 
A0000001 
000001 
20000001B0 
40040001B0 

我想追加對最終0以使它們都按照最長項的長度相同。所以,在上面的例子中,我有四個長度爲10個字符的條目,以'\ n'結尾,還有一些短條目(在實際數據中,我有約1k條短條目的200k條目)。我想要做的是找出文件中最長的字符串,然後通過並填充短的字符串;但是,我一直無法弄清楚。任何建議,將不勝感激。

+1

順便說一句,如果您將0附加到數據中,則會更改值。您可能需要考慮_prepending_ 0。 –

+0

@MatthewBurke是的,由於一個怪癖,他們的數據是相反的,所以最終實際上是開始。

回答

1

一般而言到零墊從兩側的任一個或一個字符串(使用5如例如所需的字段寬度):

$ echo '17' | awk '{printf "%0*s\n", 5, $0}' 
00017 

$ echo '17' | awk '{printf "%s%0*s\n", $0, 5-length(), ""}' 
17000 

$ echo '17' | awk '{w=int((5+length())/2); printf "%0*s%0*s\n", w, $0, 5-w, ""}' 
01700 

$ echo '17' | awk '{w=int((5+length()+1)/2); printf "%0*s%0*s\n", w, $0, 5-w, ""}' 
00170 

所以對於你的例子:

$ awk '{cur=length()} NR==FNR{max=(cur>max?cur:max);next} {printf "%s%0*s\n", $0, max-cur, ""}' file file 
40000001AA 
0000000100 
A000000100 
0000010000 
20000001B0 
40040001B0 
+1

這真的很好。我使用的是BSD系統,因此大多數其他解決方案都不能正常工作,因爲它們都是GNU特有的。 –

1

讓我們假設你在文件中這樣的值:

file=/tmp/hex.txt 

找出最長號碼的長度:

longest=$(wc -L < $file) 

現在在文件中的每個數與零證明它

while read number; do 
    printf "%-${longest}s\n" $number | sed 's/ /0/g' 
done < $file 

這將打印腳本到標準輸出:

40000001AA 
0000000100 
A000000100 
0000010000 
20000001B0 
40040001B0 
+0

請參閱[爲什麼要使用shell循環處理文本被認爲是壞行爲](https://unix.stackexchange.com/questions/169716/why-is-using-a對於這個答案的一些問題,但並不是全部,這個問題的解決方法就是從shell-loop-to-process-text-considered-bad-practice)。只需使用awk。爲了清晰,高效,魯棒性,可移植性以及大多數其他所需的軟件屬性。 –

2

當您使用Bash時,您很有可能還會使用其他GNU 工具。在這種情況下,wc可以使用-L選項輕鬆告訴您文件最大行長度的 。例如:

$ wc -L /tmp/HEX 
10 /tmp/HEX 

填充可以做這樣的:

$ while read i; do echo $(echo "$i"0000000000 | head -c 10); done < /tmp/HEX 
40000001AA 
0000000100 
A000000100 
0000010000 
20000001B0 
40040001B0 

一個班輪:

while read i; do eval printf "$i%.s0" {1..$(wc -L /tmp/HEX | cut -d ' ' -f1)} | head -c $(wc -L /tmp/HEX | cut -d ' ' -f1); echo; done < /tmp/HEX 
3

使用標準的兩通AWK:

awk 'NR==FNR{if (len < length()) len=length(); next} 
    {s = sprintf("%-*s", len, $0); gsub(/ /, "0", s); print s}' file file 

40000001AA 
0000000100 
A000000100 
0000010000 
20000001B0 
40040001B0 

或者使用gnu wcawk

awk -v len="$(wc -L < file)" ' 
    {s = sprintf("%-*s", len, $0); gsub(/ /, "0", s); print s}' file 

40000001AA 
0000000100 
A000000100 
0000010000 
20000001B0 
40040001B0 
+1

謝謝埃德,這是一個非常好的建議,一如既往:) – anubhava