我對程式的輸出有問題。我需要在 bash 中啟動一個命令並獲取其輸出(一個字串)並將其拆分以在某些位置添加新行。該字串如下所示:
battery.charge: 90 battery.charge.low: 30 battery.runtime: 3690 battery.voltage: 230.0 device.mfr: MGE UPS SYSTEMS device.model: Pulsar Evolution 500
基本上它是一個xxx.yy.zz:值,但該值可能包含空格。這是我想要得到的輸出
battery.charge: 90
battery.charge.low: 30
battery.runtime: 3690
battery.voltage: 230.0
device.mfr: MGE UPS SYSTEMS
device.model: Pulsar Evolution 500
我有一個想法,搜尋第一個點,然後從該位置向後查找空間,以便在那裡放置新行,但我不確定如何在 Bash 中實現它。
答案1
純bash解決方案,沒有使用外部工具來處理字串,只是參數擴展:
#! /bin/bash
str='battery.charge: 90 battery.charge.low: 30 battery.runtime: 3690 battery.voltage: 230.0 device.mfr: MGE UPS SYSTEMS device.model: Pulsar Evolution 500'
IFS=: read -a fields <<< "$str"
for (( i=0 ; i < ${#fields[@]} ; i++ )) ; do
f=${fields[i]}
notfirst=$(( i>0 ))
last=$(( i+1 == ${#fields[@]} ))
(( notfirst )) && echo -n ${f% *}
start=('' $'\n' ' ')
colon=('' ': ')
echo -n "${start[notfirst + last]}${f##* }${colon[!last]}"
done
echo
說明:$notfirst
和$last
是布林值。第一個欄位不會列印最後一個空格之前的部分${f% *}
,因為沒有這樣的東西。$start
並$colon
保存分隔字段的各種字串:第一項notfirst + last
為 0,因此沒有任何內容前置,對於其餘行,$notfirst
為 1,因此打印換行符,對於最後一行,加法給出 2,因此打印出一個空格。然後,列印最後一個空格之後的部分${f##* }
。除最後一行外,所有行都列印冒號。
答案2
使用 GNU sed,您可以匹配以 結尾的每個連續字串(即沒有空格):
,然後在除第一個字串之外的所有字串之前放置一個換行符:
sed 's/[^[:space:]]\+:/\n&/g2'
如果您的 sed 版本不支援gn
擴展,您可以使用普通g
修飾符
sed 's/[^[:space:]]\{1,\}:/\
&/g'
除了在第一個鍵之前列印一個額外的換行符之外,它的工作方式相同。您可以使用perl -pe 's/\S+:/\n$&/g'
相同的附帶條件(可能有 GNU sed 的 perl 等效項,g2
但我不知道)。
答案3
一個perl
辦法:
$ perl -pe 's{\S+:}{$seen++ ? "\n$&" : "$&"}ge' file
battery.charge: 90
battery.charge.low: 30
battery.runtime: 3690
battery.voltage: 230.0
device.mfr: MGE UPS SYSTEMS
device.model: Pulsar Evolution 500
解釋
\S+:
匹配字串結尾為:
.- 對於所有符合的字串,我們在它們之前插入換行符(
("\n$&")
第一個除外)($seen++)
。
答案4
這是一種簡單的方法,假設您不關心輸入中的製表符和換行符(如果有)被轉換為普通空格,則該方法應該有效。
這個想法很簡單:在空格上分割輸入,並列印每個標記,除了在:
前面添加以換行符結尾的標記(並在其他標記前面重新添加一個空格)。變數$count
和相關變數if
僅用於防止初始空白行。如果沒問題的話可以刪除。 (該腳本假定輸入位於intput
目前目錄中呼叫的檔案中。)
#! /bin/bash
count=0
for i in $(<input) ; do
fmt=
if [[ $i =~ :$ ]] ; then
if [[ $count -gt 0 ]] ; then
fmt="\n%s"
else
fmt="%s"
fi
((count++))
else
fmt=" %s"
fi
printf "$fmt" "$i"
done
echo
echo "Num items: $count"
我希望有人能想出一個更好的選擇。
$ cat input
battery.charge: 90 battery.charge.low: 30 battery.runtime: 3690 battery.voltage: 230.0 device.mfr: MGE UPS SYSTEMS device.model: Pulsar Evolution 500
$ ./t.sh
battery.charge: 90
battery.charge.low: 30
battery.runtime: 3690
battery.voltage: 230.0
device.mfr: MGE UPS SYSTEMS
device.model: Pulsar Evolution 500
Num items: 6