> lsblk -o NAME,LABEL,FSTYPE,MOUNTPOINT,SIZE,TYPE -x NAME
NAME LABEL FSTYPE MOUNTPOINT SIZE TYPE
nvme0n1 894.3G disk
nvme0n1p1 [SWAP] 4G part
nvme0n1p2 1G part
nvme0n1p3 root /home/cg/root 889.3G part
我需要 csv 格式的這個命令的輸出,但是到目前為止我嘗試過的所有方法都不能正確處理空值,因此會生成像我用 sed 得到的這樣的壞行:
> lsblk -o NAME,LABEL,FSTYPE,MOUNTPOINT,SIZE,TYPE -x NAME | sed -E 's/ /,/g'
NAME,LABEL,FSTYPE,MOUNTPOINT,SIZE,TYPE
nvme0n1,894.3G,disk
nvme0n1p1,[SWAP],4G,part
nvme0n1p2,1G,part
nvme0n1p3,root,/home/cg/root,889.3G,part
知道如何為空欄位添加額外的逗號嗎?
NAME,LABEL,FSTYPE,MOUNTPOINT,SIZE,TYPE
nvme0n1,,,,894.3G,disk
uj5u.com熱心網友回復:
確保可能為空的欄位位于行尾。然后按照要求的順序重新排列它們。
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,LABEL -x NAME | awk '{ print $1,";",$6,";",$4,";",$5,";",$2,";",$3 }'
uj5u.com熱心網友回復:
只是:
lsblk -o NAME,LABEL,FSTYPE,MOUNTPOINT,SIZE,TYPE -x NAME -r | tr ' ' ','
uj5u.com熱心網友回復:
不是真正的 bash,但一個快速而骯臟的 Perl 會是這樣的:
my $state=0;
my @input=<>;
my $maxlength=0;
for my $line ( 0 .. $#input){
my $curlength= length($input[$line]);
if ($curlength>$maxlength){$maxlength=$curlength;}
}
my $fill=' ' x $maxlength;
for my $line ( 0 .. $#input){
chomp $input[$line];
$input[$line]="$input[$line] $fill";
}
for (my $pos=0; $pos<$maxlength; $pos ){
my $spacecol=1;
for my $line ( 0 .. $#input){
if (substr($input[$line],$pos,1) ne ' '){
$spacecol=0;
}
}
if ($spacecol==1){
for my $line ( 0 .. $#input){
substr($input[$line],$pos,1)=';';
}
}
}
for my $line ( 0 .. $#input){
print "$input[$line]\n";
}
uj5u.com熱心網友回復:
假設:
- 輸出格式是固定寬度的
- 標頭記錄不包含任何空白欄位
- 沒有欄位包含空格(即,欄位之間僅出現空格)
設計概述:
- 決議標頭以獲取每個欄位的初始索引;如果所有列都是左對齊的,那么這就是我們需要做的所有事情,但是,由于存在右對齊的列(例如,
SIZE),我們需要尋找比相關標題欄位更長的右對齊值(即,該值的索引低于關聯的標頭) - 對于非標題行,我們遍歷我們的潛在欄位集,使用
substr()/match()用于查找行中的非空格欄位并... - 如果所述欄位在下一個欄位的索引之前開始和結束,則將該欄位的值添加到我們的
output 變數中,但是...... - 如果所述欄位在下一個欄位的索引之前開始但在下一個欄位的索引之后結束,那么我們正在查看下一個欄位的右對齊值,該值恰好具有比相關標頭的索引更早的索引;在這種情況下,更新下一個欄位的索引并向我們的
output 變數添加一個空白值(對于當前欄位) - 如果所述欄位在下一個欄位的索引之后開始,則當前欄位為空;再次,將空/空白值添加到我們的
output 變數中 - 一旦我們完成了一行輸入的處理,將
output 列印到 stdout
一個awk想法:
awk '
BEGIN { OFS="," }
# use header record to determine initial set of indexes
FNR==1 { maxNF=NF
header=$0
out=sep=""
for (i=1;i<=maxNF;i ) {
match(header,/[^[:space:]] /) # find first non-space string
ndx[i]=ndx[i-1] prevlen RSTART - (i==1 ? 0 : 1) # make note of index
out=out sep substr(header,RSTART,RLENGTH) # add value to our output variable
sep=OFS
prevlen=RLENGTH # need for next pass through loop
header=substr(header,RSTART RLENGTH) # strip off matched string and repeat loop
}
print out # print header to stdout
ndx[1]=1 # in case 1st field is right-justified, override index and set to 1
next
}
# for rest of records need to determine which fields are empty and/or which fields need the associated index updated
{ out=sep=""
for (i=1;i<maxNF;i ) { # loop through all but last field
restofline=substr($0,ndx[i]) # work with current field thru to end of line
if ( match(restofline,/[^[:space:]] /) ) # if we find a non-space match ...
if ( ndx[i]-1 RSTART < ndx[i 1] ) # if match starts before index of next field and ...
if ( ndx[i]-1 RSTART RLENGTH < ndx[i 1] ) # ends before index of next field then ...
out=out sep substr(restofline,RSTART,RLENGTH) # append value to our output variable
else { # else if match finished beyond index of next field then ...
out=out sep "" # this field is empty and ...
diff=ndx[i 1]-(ndx[i] RSTART-1) # figure the difference and ...
ndx[i 1]-=diff # update the index for the next field
}
else # current field is empty
out=out sep ""
sep=OFS
}
field=substr($0,ndx[maxNF]) # process last field
gsub(/[[:space:]]/,"",field) # remove all remaining spaces
print out, field # print new line to stdout
}
' lsblk.out
這會產生:
NAME,LABEL,FSTYPE,MOUNTPOINT,SIZE,TYPE
nvme0n1,,,,894.3G,disk
nvme0n1p1,,,[SWAP],4G,part
nvme0n1p2,,,,1G,part
nvme0n1p3,root,,/home/cg/root,889.3G,part
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/520109.html
標籤:重击解析格式化
上一篇:將范圍轉換為字串
