Принятие формата даты является yyyy-mm-dd hh:mi:ss, можно использовать этот сценарий жемчуга:
#!/usr/bin/perl -w
open(FILEH,"<","your.log") or die "cannot open file";
my $date = "0000-00-00 00:00:00";
while(<FILEH>) {
if( /^([A-Z][a-z]{2}\s[A-Z][a-z]{2}\s[0-9]+\s[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\s[0-9]{4})$/ ) {
$date = $1;
}
else {
print "$date $_";
}
}
Измените your.log с полным путем Вашего файла журнала.
Если на случайном этапе вы просто пытаетесь обработать кавычки для повторного использования оболочки, то вы можете сделать это , не удаляя их , и это также просто:
aq() { sh -c 'for a do
alias "$((i=$i+1))=$a"
done; alias' -- "$@"
}
Эта оболочка функции цитирует любой массив arg, который вы передаете, и увеличивает его вывод на итерабельный аргумент.
Здесь это с несколькими аргументами:
aq \
"here's an
ugly one" \
"this one is \$PATHpretty bad, too" \
'this one```****```; totally sucks'
1='here'"'"'s an
ugly one'
2='this one is $PATHpretty bad, too'
3='this one```****```; totally sucks'
Этот выход из тире
, который, как правило, безопасно кавычки в одной кавычке, как '«'» '
. bash
будет выполнять '\"
.
В любой оболочке POSIX с $ IFS
и $ *
можно быстрее всего заменить набор байтов, отличных от пустых и пустых.
set -f; IFS=\"\'\`; set -- $var; printf %s "$*"
"some ""crazy """"""""string ""here
Там я просто printf
это, чтобы вы могли видеть, но, конечно, если бы я сделал:
var="$*"
..., а не printf
команда $ var
значение будет то, что вы видите на выходе там.
Когда я задаю -f
, я инструктирую оболочку не на glob - в случае, если последовательность содержит символы, которые можно истолковать как glob узоров. Я делаю это, потому что синтаксический анализатор оболочек расширяет паттерны глоба после он выполняет разделение поля на переменные. глоббинг может быть повторно включен, как набор + f
. В общем - в сценариях - я считаю полезным задать свой удар, как:
#!/usr/bin/sh -f
И затем явно включить глоббинг с установить + f
на любой линии, которую я мог бы захотеть.
Разделение полей выполняется на основе символов в $ IFS
.
Существует два вида значений $ IFS
- $ IFS
пробел и $ IFS
пробел. $ IFS
пробел (космос, табуляция, новая строка) разделенные поля определяются как разделяемые последовательностью на одно поле (или вообще отсутствуют, если они не предшествуют чему-либо другому) - так что...
IFS=\ ; var=' '; printf '<%s>' $var
<>
Но все остальные указаны для вычисления одного поля для каждого вхождения - они не усечены.
IFS=/; var='/////'; printf '<%s>' $var
<><><><><>
Все расширения переменных по умолчанию представляют собой массивы данных с разделителями $ IFS
- они разделены на отдельные поля в соответствии с $ IFS
. Когда вы "
- цитируете одно из них, вы переопределяете это свойство массива и оцениваете его как один ряд.
Так что, когда я это делаю...
IFS=\"\'\`; set -- $var
Я настройкой массив аргументов оболочки к множеству полей $ IFS
, разделенных расширением $ var
. При расширении его составляющих значений для символов, содержащихся в $ IFS
, теряется - теперь они являются только разделителями полей - \0NUL
.
«$ *»
- как и другие переменные расширения с двойными кавычками - также переопределяет качества разделения поля $ IFS
. Но, в дополнение ,он заменяет первый байт в $ IFS
для каждого разделенного поля в «$ @»
. Так как «
было первым значением в $ IFS
все последующие разделители становятся »
в «$ *»
. И "
не обязательно находиться в $ IFS
при разделении. Можно полностью изменить $ IFS
после наборов -- $ args
на другое значение, и его новый первый байт появится для разделителей полей в «$ *»
. Более того, вы можете удалить все следы их полностью как:
set -- $var; IFS=; printf %s "$*"
some crazy string here
-121--24039- Сложнее, чем другие ответы, но это использует getopt
для обработки анализа для вас. Еще одна альтернатива.
getopt -aql 'Dapp.name:' $(\
ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
пикосекунда - AF-u SAS | grep Ява | grep-v grep
tr-s ''
«сжимает» несколько мест в одинарный интервал при подготовке к , сокращается
, сокращается,-d' '-f8-
разделяет линию местами и захватывает все поля после того, как 8 содержащих, результат /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java-denv=dev-dapp.name=myapp-xms512m-xmx1g-dlog.dir =/apps/java/logs
getopts-aql 'Dapp.name:$ (...)
анализирует параметры команды и выводит только длинное имя, соответствующее Dapp.name
, которое имеет значение (обозначается как :
), результатом является --Dapp.name 'myApp' --
cut -d «'» -f2
захватов материал в одиночных кавычках myApp
Каждый раз, когда вы используете ps... | grep...
и должны исключить grep из результатов, вы делаете это неправильно.
Нулевое правило анализа выходных данных ps
заключается в использовании более надежных инструментов, таких как pgrep
, если они доступны. Если имеется pgrep, то pgrep -f java
перечисляет все процессы, выполняющие команду java
. Параметр -l
добавляет командную строку для каждого процесса.
Для извлечения аргумента -Dapp.name
можно использовать sed. Сопоставьте всю линию, организуйте ввод интересной части в группе и распечатайте эту группу.
pgrep -lf java | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'
Первое правило анализа выходных данных ps
заключается в использовании опции -o
для выбора необходимых полей. Здесь вас интересуют только аргументы команды, поэтому напечатайте только это.
ps -e -o args= | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'
Вы не показываете получаемое сообщение об ошибке, но вероятно
grep: unknown devices method
Это потому, что, как и все или, по крайней мере, большинство других программ командной строки, grep
предполагает, что все, что начинается с -
, является опцией и пытается разобрать ее как таковую. В этом случае -D
используется для инструктажа grep
о том, как работать с файлом устройства (подробнее см. man grep
). Один из способов обойти это - использовать --
, который сообщает grep
, что все, что следует далее, не является флагом опции.
Комбинируя это с возможностью PCRE GNU grep
, вы можете сделать:
ps -af -u sas | grep -v grep | grep -Po -- '*-\KDapp.name=[^\s]+'
Регулярное выражение ищет -
и отбрасывает его (\K
), затем строка Dapp.name=
, за которой следует как можно больше непробеленных символов. Вывод:
Dapp.name=myApp
Если вы хотите, чтобы часть myApp
сохранялась в переменной, я буду искать только это:
ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+'
Чтобы присвоить ее переменной:
$ app="$(ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+')"
$ echo $app
myApp
Однако, вы никогда не должны grep
выводить ps
для такого рода вещей, это то, что pgrep
для:
app="$(pgrep -a java | grep -Po -- '^Dapp.name=\K[^\s]+')"
Более сложный, чем другие ответы, но он использует getopt
, чтобы справиться с синтаксическим анализом для вас. Еще одна альтернатива.
getopt -aql 'Dapp.name:' $(\
ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
ps -af -u sas | grep java | grep -v grep
tr -s "
"сжимает" несколько пробелов в одном пространстве при подготовке к cut
cut -d''' -f8-
разбивает строку на пробелы и захватывает все поля после 8 включительно, в результате /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25. x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs
getopts -aql 'Dapp.name:' $(..... )
разбирает опции команды и выводит только длинное имя, совпадающее с Dapp.name
, которое имеет значение (обозначаемое :
), в результате чего получается -Dapp.name 'myApp' --
cut -d""". -f2
хватает материал в одинарных кавычках myApp
Я бы использовал pgrep
вместо ps
так:
$ pgrep -fa java | grep -op "(<=-Dapp.name=)\w+"
Это вернет все процессы, которые соответствуют java
, а затем отфильтровывает те, которые показывают только те, которые содержат -Dapp.name=
. Последний бит, \w+
покажет имя программы, предполагая, что оно не содержит пробелов.
ПРИМЕЧАНИЕ: Переключение -P
на grep
позволяет указать вещи с помощью PCRE - Perl Compatible Regular Expressions. Не все версии grep
поддерживают его, но большинство из них включены в более современные версии Linux.
Если Вам нужен весь вывод ключа/значения, то измените так:
$ pgrep -fa java | grep -oP -- "-Dapp.name=\w+"