#string #if-statement #text #awk #substring
#строка #if-оператор #текст #awk #подстрока
Вопрос:
У меня есть большой текстовый файл («,» в качестве разделителя) с некоторыми данными и строкой:
2014:04:29:00:00:58:GMT: subject=BMRA.BM.T_GRIFW-1.FPN, message={SD=2014:04:29:00:00:00:GMT,SP=5,NP=3,TS=2014:04:29:01:00:00:GMT,VP=4.0,TS=2014:04:29:01:29:00:GMT,VP=4.0,TS=2014:04:29:01:30:00:GMT,VP=3.0}
2014:04:29:00:00:59:GMT: subject=BMRA.BM.T_GRIFW-2.FPN, message={SD=2014:04:29:00:00:00:GMT,SP=5,NP=2,TS=2014:04:29:01:00:00:GMT,VP=3.0,TS=2014:04:29:01:30:00:GMT,VP=3.0}
Я хотел бы найти строки, содержащие ‘T_GRIFW’, а затем распечатать поле в размере 1 доллара США начиная с ‘subject’ и далее, и только времена и значения с плавающей запятой начиная с 2 долларов США. Кроме того, я хочу включить оператор if, чтобы, если поле $ 4 == ‘NP= 3’, только поля $5,$6,$9,$10 печатаются после предыдущих полей, и если $ 4 == ‘NP= 2’, печатаются все последующие поля (только с временным значением и плавающими значениями)
Например, результатом двух выборочных строк будет:
subject=BMRA.BM.T_GRIFW-1.FPN,2014:04:29:00:00:00,5,3,2014:04:29:01:00:00,4.0,2014:04:29:01:30:00,3.0
subject=BMRA.BM.T_GRIFW-2.FPN,2014:04:29:00:00:00,5,2,2014:04:29:01:00:00,3.0,2014:04:29:01:30:00,3.0
Я знаю, что это сложно, и я изо всех сил старался быть подробным в своем описании. Основной код, который у меня есть на данный момент, это:
awk 'BEGIN {FS=","}{OFS=","} /T_GRIFW-1.FPN/ {print $1}' tib_messages.2014-04-29
МИЛЛИОН БЛАГОДАРНОСТЕЙ!
Комментарии:
1. Пока у вас не так много. Старайтесь усерднее!
2. Ваш вывод не имеет смысла, поскольку он не соответствует вашему условию. Вы сказали, что если
NP=3
, то только поля $5,$6,$9,$10 должно печататься.3. Привет, Ooga, извините за двусмысленность, я имел в виду после, только $5,$6,$9,$10 должно печататься.
Ответ №1:
Вот исполняемый файл awk, который создаст желаемый результат:
#!/usr/bin/awk -f
# use a more complicated FS => field numbers counted differently
BEGIN { FS="=|,"; OFS="," }
$2 ~ /T_GRIFW/ amp;amp; $8=="NP" {
str="subject=" $2 OFS
# strip ":GMT" from dates and "}" from everywhere
gsub( /:GMT|[}]/, "")
# append common fields to str with OFS
for(i=5;i<=13;i =2) str=str $i OFS
# print the remaining fields and line separator
if($9==3) { print str $19, $21 }
else if($9==2) { print str $15, $17 }
}
Помещение этого в файл с именем awko
и последующая его модификация awko data
приводит к:
subject=BMRA.BM.T_GRIFW-1.FPN,2014:04:29:00:00:00,5,3,2014:04:29:01:00:00,4.0,2014:04:29:01:30:00,3.0
subject=BMRA.BM.T_GRIFW-2.FPN,2014:04:29:00:00:00,5,2,2014:04:29:01:00:00,3.0,2014:04:29:01:30:00,3.0
Я разместил комментарии в сценарии, но вот некоторые вещи, которые можно было бы изложить лучше:
- Использование более сложного
FS
означает, что вам не нужно повторно обрабатывать=
данные поля - Я «обманул» и просто жестко запрограммировал
subject
(который теперь находится в конце$1
) дляstr
:GMT
и}
оказались единственными данными, которые необходимо было принудительно удалить- При этом
FS
даты и числа отделены друг от друга, но все еще доступны для цикла - В любом последнем
print
вызовеstr
уже заканчивается наOFS
, поэтому запятую между ним и следующим полем можно пропустить
Комментарии:
1. Я очень рад, что некоторые люди здесь все еще проявляют большое терпение к некоторым из нас, которые изо всех сил пытаются освоить веревки! Большое спасибо n0741337 и S. Ahn!
Ответ №2:
Если я понимаю ваши требования, будет работать следующее:
BEGIN {
FS=","
OFS=","
}
/T_GRIFW/ {
split($1, subject, " ")
result = subject[2] OFS
delete arr
counter = 1
for (i = 2; i <= NF; i ) {
add = 0
if ($4 == "NP=3") {
if (i == 5 || i == 6 || i == 9 || i == 10) {
add = 1
}
}
else if ($4 == "NP=2") {
add = 1
}
if (add) {
counter = counter 1
split($i, field, "=")
if (match(field[2], "[0-9]*.[0-9] |GMT")) {
arr[counter] = field[2]
}
}
}
for (i in arr) {
gsub(/{|}/,"", arr[i]) # remove curly braces
result = result arr[i] OFS
}
print substr(result, 0, length(result)-1)
}
Комментарии:
1. Большое вам спасибо, С. Ан!!