2016-11-28 4 views
0

У меня есть несколько файлов журналы с целевыми строками, которые я хотел, чтобы «Grep», такие как:ломтик строки с несколькими разделителями

EGPA019_90pc.recode.2.log:Cross-Entropy (masked data): 0.556984 

Я хочу, чтобы нарезать из «2» и «0.556984», простирающийся с вкладка в файл

Так что, если я вхожу:

grep "Cross-Entropy (masked data):" *.log | cut -d '.' -f 3 >> targetFile.txt 

Я получаю "2", а также:

grep "Cross-Entropy (masked data):" *.log | cut -d ' ' -f 4 >> targetFile.txt 

Я получаю «0.556984». Но как я могу написать это в одной строке кода, чтобы получить «2», а затем вкладку «0,556984» в той же строке в моем целевом файле?

Большое спасибо

Clive

ответ

2

Вы можете использовать grep и немного bash встроенной функции Regex.

grep -h "Cross-Entropy (masked data):" *.log | while IFS= read -r string; do 
     [[ "$string" =~ .recode.([[:digit:]]+).*:\ (.*)$ ]] 
     printf "%s\t%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]//[[:blank:]]}"; 
done 

Мои входные файлы

$ cat *.log 
EGPA019_90pc.recode.2.log:Cross-Entropy (masked data): 0.556984 
EGPA019_90pc.recode.9.log:Cross-Entropy (masked data): 0.996984 
EGPA019_90pc.recode.7.log:Cross-Entropy (masked data): 0.756984 

$ grep -h "Cross-Entropy (masked data):" *.log | while IFS= read -r string; do 
     [[ "$string" =~ .recode.([[:digit:]]+).*:\ (.*)$ ]] 
     printf "%s\t%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]//[[:blank:]]}"; done 
2  0.556984 
9  0.996984 
7  0.756984 

Объяснение: -

  1. Am, используя встроенные функции bash REGEX захватить требуемую строку, вместо того, чтобы использовать другие родные инструменты.
  2. Выходной сигнал grep подается по трубопроводу, чтобы применить regEx [ "$string" =~ recode.([[:digit:]]+).*:\ (.*)$ ]], который фиксирует требуемые записи, цифру и десятичное число.
  3. Использование printf для печати этих переменных. Второго захвата, т.е. десятичных цифр имеют пробельные символы в начале, удаляя его "${BASH_REMATCH[2]//[[:blank:]]}"

Вы также можете обернуть его вокруг в сценарий оболочки, как показано ниже: -

#!/bin/bash 

while IFS= read -r string; do 
    [[ "$string" =~ .recode.([[:digit:]]+).*:\ (.*)$ ]] 
    printf "%s\t%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]//[[:blank:]]}" 
done < <(grep -h "Cross-Entropy (masked data):" *.log) 

Or) Используйте grep с флагом PCRE -P и xargs для фильтрации выходных данных.

grep -Pho '\.recode\.\K\d+|: \K.*' *.log | xargs -n2 -d'\n' 
2 0.556984 
9 0.996984 
7 0.756984 

(или) использовать более простую perl синтаксис Regex.

perl -lne 'print "$1 $2" if /\.recode\.(\d+).*:\s+(.*)/' *.log 
2 0.556984 
9 0.996984 
7 0.756984 
+0

Привет, это просто дает мне много белого пространства без информации я хочу. Спасибо – user3329732

+0

Что такое печать :? Можете ли вы поделиться выходом? В тексте примера, который вы дали, он работал отлично. Либо вы вызываете его неправильно, либо ваши строки ввода различны. – Inian

+0

У меня есть 10 строк на моем входе, и я получаю 10 строк пробела назад. Ваш вход выглядит идентичным. – user3329732

0

Я думаю, что я хотел бы сделать это с помощью awk, а не анализа вывода grep.

У меня нет данных, чтобы проверить это, но мне кажется, что следующее должно работать.

awk '/^Cross-Entropy \(masked data\):/ {split(FILENAME,a,".");printf("%s\t%s\n", a[3], $NF}' *.log 

Это немного длиннее, чем однострочный.Как самостоятельный сценарий, он может выглядеть следующим образом:

#!/usr/bin/awk -f 

/^Cross-Entropy \(masked data\):/ { 
    split(FILENAME,a,".") 
    printf("%s\t%s\n", a[3], $NF 
} 

Сохранить в файл, сделать его исполняемым, и вы сами совершенно новая команда оболочки.

Обратите внимание, что это работает, используя разбиение поля, НЕ с помощью регулярного выражения.

0

Вы можете удалить ненужные вещи с sed:

grep "Cross-Entropy (masked data):" *.log | sed 's/.*recode.//;s/\..*: //' 

grep и sed можно комбинировать:

sed -n '/Cross-Entropy (masked data):/ {s/.*recode.//;s/\..*: //;p}' *.log 
Смежные вопросы