私のプログラムの出力に問題があります。 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