2010-04-24 2 views
2

Я пытаюсь вытащить динамику из нагрузки, которую я запускаю с помощью bash. Я добрался до точки, где я получаю нужную строку, теперь из этого хочу получить определенную информацию, которая может меняться. Строка, которая получает возвращается следующим образом:Как передать информацию из строки

Records: 2910 Deleted: 0 Skipped: 0 Warnings: 0 

Каждый из числа может и будет изменяться по длине, но общая структура останется тем же. То, что я хочу сделать, это быть в состоянии получить эти цифры и загрузить их в некоторых переменных Баш именно:

RECORDS=?? 
DELETED=?? 
SKIPPED=?? 
WARNING=?? 

В регулярных выражениях я хотел бы сделать это следующим образом:

Records: (\d*?) Deleted: (\d*?) Skipped (\d*?) Warnings (\d*?) 

и использовать 4 группы в мои переменные.

+0

http://stackoverflow.com/questions/918886/split-string-on-delimiter-in-bash –

+0

Этот вопрос относится к разбиению строки на основе разделителя, я просто wan t, чтобы вытащить числа, и у меня нет общего разделителя. –

+1

Фактически пространство между элементами выглядит как соответствующий разделитель. См. Сокращенную версию сценария в ответе. – rmarimon

ответ

4

Вы можете использовать регулярные выражения соответствия в Bash версии> = 3.2:

[[ $line =~ ([[:digit:]]+).*([[:digit:]]+).*([[:digit:]]+).*([[:digit:]]+) ]] 

RECORDS=${BASH_REMATCH[1]} 
DELETED=${BASH_REMATCH[2]} 
SKIPPED=${BASH_REMATCH[3]} 
WARNING=${BASH_REMATCH[4]} 
+0

Отличный ответ. Я бы выбрал тебя, хотя написал еще один ответ. Это некоторая функциональность bash, о которой я не знал. – rmarimon

+0

@rmarimon, это работает, но только тогда, когда ваша строка точно так же, как показано каждый раз. Если данных больше, это не сработает. – ghostdog74

3

Встроенная read команда будет делать трюк:

read TMP1 RECORDS TMP2 DELETED TMP3 SKIPPED TMP4 WARNING 

Update: Вы можете также использовать set:

set $line 
RECORDS=$2 
DELETED=$4 
SKIPPED=$6 
WARNING=$8 
+0

чтение - это захват пользовательского ввода, im не вводящий это вручную, эта строка установлена ​​в переменную с именем '$ r' –

+0

@Russ. Это обновленный ответ, который также работает со строками. – Bolo

+2

@Russ: 'read' может получать значения со стандартного ввода:' s = "foo bar baz"; read a b c <<< $ s' –

0

Вы можете попробовать что-то с 'СЭД' или 'вырезать' в зависимости от строения такой линии:

#!/bin/sh                  

DYNAMIC="Records: 2910 Deleted: 1 Skipped: 2 Warnings: 3" 

RECORDS=`echo "$DYNAMIC" | sed 's/.*Records: \([0-9]*\).*/\1/g'` 
DELETED=`echo "$DYNAMIC" | sed 's/.*Deleted: \([0-9]*\).*/\1/g'` 
SKIPPED=`echo "$DYNAMIC" | sed 's/.*Skipped: \([0-9]*\).*/\1/g'` 
WARNINGS=`echo "$DYNAMIC" | sed 's/.*Warnings: \([0-9]*\).*/\1/g'` 

echo "Records $RECORDS" 
echo "Deleted $DELETED" 
echo "Skipped $SKIPPED" 
echo "Warnings $WARNINGS" 

echo "$DYNAMIC" | cut -d " " -f2 
echo "$DYNAMIC" | cut -d " " -f4 
echo "$DYNAMIC" | cut -d " " -f6 
echo "$DYNAMIC" | cut -d " " -f8 
+0

Слишком сложно, я предпочитаю решение Боло. –

1

Вот функция оболочки можно использовать, что просто создает ряд пар имя/значение. Это предполагает все отформатированы как вы сказали, но это легко изменить:

parseline() { 
    while [ $# -ge 2 ] ; do 
     eval $(echo $1 | tr -d : | tr '[a-z]' '[A-Z]')="$2" 
     shift 2 
    done 
} 

Исполнить это нравится:

$ parseline Records: 2910 Deleted: 0 Skipped: 0 Warnings: 0 
$ echo $RECORDS 
2910 
$ echo $WARNINGS 
0 
0
#!/bin/bash 
s="Records: 2910 Deleted: 0 Skipped: 0 Warnings: 0" 
s=${s//: /=} 
for i in $(printf ${s// /"\n"}) 
do 
eval $i 
done 

echo "Records: $Records" 
echo "Deleted: $Deleted" 
echo "Skipped: $Skipped" 
echo "Warnings: $Warnings" 

выход

$ ./shell.sh 
Records: 2910 
Deleted: 0 
Skipped: 0 
Warnings: 0 
Смежные вопросы