내 프로그램의 출력에 문제가 있습니다. 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