2015-10-15 35 views
0

相同的長度,我需要的是第4列的所有號碼有4個字符讓數字在特定的列在BASH

輸入

AGAP4 2061 0.534207 917.0 0 0 1 
AGAP5 2061 0.536148 101.5 0 0 8 
AGBL1 3201 0.514214 917.9 0 0 2 
AGBL2 2709 0.444814 12.5 0 0 1 

所需的輸出

AGAP4 2061 0.534207 917.0 0 0 1 
AGAP5 2061 0.536148 101.5 0 0 8 
AGBL1 3201 0.514214 917.9 0 0 2 
AGBL2 2709 0.444814 12.50 0 0 1 

回答

1

這不是你所要求的,但提供了一致的寬度:

awk '{$4=sprintf("%06.2f", $4)}1' input 

主要生產:

AGAP4 2061 0.534207 917.00 0 0 1 
AGAP5 2061 0.536148 101.50 0 0 8 
AGBL1 3201 0.514214 917.90 0 0 2 
AGBL2 2709 0.444814 012.50 0 0 1 
+0

謝謝@Willian這是真正有用的和易於應用! – Jontexas

1

這是相當不靈活,但與你的具體問題涉及:

awk 'length($4) == 4 { $4 = $4 "0" }1' file 

它所做的是增加了一個0到第4場結束,如果它是4個字符長。

如果需求更復雜,例如長度可以變化多個數字,那麼你應該更新你的問題來顯示一些不同的輸入。

1

在bash(或POSIX shell)中,您的主要內置格式化工具是printf。可以讀取每一行的第一個4列,其餘的一些虛擬變量,然後用printf格式化列於特定寬度的每個打印它們,根據需要:

#!/bin/bash 

while read -r c1 c2 c3 c4 stuff; do 
    printf "%5s %4s %8s %5s %s\n" $c1 $c2 $c3 $c4 "$stuff" 
done < "$1" 

exit 0 

輸入

$ cat dat/agap.txt 
AGAP4 2061 0.534207 917.0 0 0 1 
AGAP5 2061 0.536148 101.5 0 0 8 
AGBL1 3201 0.514214 917.9 0 0 2 
AGBL2 2709 0.444814 12.5 0 0 1 

輸出

$ bash fmtagap.sh dat/agap.txt 
AGAP4 2061 0.534207 917.0 0 0 1 
AGAP5 2061 0.536148 101.5 0 0 8 
AGBL1 3201 0.514214 917.9 0 0 2 
AGBL2 2709 0.444814 12.5 0 0 1 

printf b中ash與C中的格式字符串和格式說明符相同。您可以閱讀有關使用man 3 printf中的格式進行的所有操作。另外bash增加了一些,如printf -v varname "fmt string"來格式化並將結果保存在varname

格式字符串的一個限制是填充。雖然您可以在左側填寫0墊,但您不能在0填充右側的數字。無論您使用%s字符串轉換還是%5.1f浮點轉換,您都被限制爲左填充和字段寬度規範。

您當然可以在打印之前檢查每個變量的長度,然後使用0填充這種方式,但是這是關於您開始詢問的一點,外部Shell實用程序可以爲我做這些事情...... 。但是,爲了完整性:

#!/bin/bash 

while read -r c1 c2 c3 c4 stuff; do 
    while [ ${#c4} -lt 5 ]; do 
     c4="${c4}0" 
    done 
    printf "%s %s %s %s %s\n" $c1 $c2 $c3 $c4 "$stuff" 
done < "$1" 

exit 0 

輸出

$ bash fmtagap.sh dat/agap.txt 
AGAP4 2061 0.534207 917.0 0 0 1 
AGAP5 2061 0.536148 101.5 0 0 8 
AGBL1 3201 0.514214 917.9 0 0 2 
AGBL2 2709 0.444814 12.50 0 0 1 
+0

謝謝@David!真棒解釋! – Jontexas

1

Perl的溶液類似@威廉的AWK溶液:

perl -lane '$F[3] = sprintf("%06.2f", $F[3]); print join " ",@F' input

-a autosplits各行成@F陣列

輸出:

AGAP4 2061 0.534207 917.00 0 0 1 
AGAP5 2061 0.536148 101.50 0 0 8 
AGBL1 3201 0.514214 917.90 0 0 2 
AGBL2 2709 0.444814 012.50 0 0 1 

使用substr生產要求您提供的格式:

perl -lane '$F[3] = substr(sprintf("%5.2f", $F[3]),0,5); print join " ",@F' input

AGAP4 2061 0.534207 917.0 0 0 1 
AGAP5 2061 0.536148 101.5 0 0 8 
AGBL1 3201 0.514214 917.9 0 0 2 
AGBL2 2709 0.444814 12.50 0 0 1