Если вы имеете в виду, что замена не должна выполняться, если имеется более 8 соседних (TAB)
s, вы можете сделать:
sed '
s/_/_u/g; # escape _
s/|/_p/g; # escape |
s/(TAB)/|/g; # use a single character in place of (TAB)
s/.*/<&>/; # add leading and trailing non-| character
s/\([^|]\)|\{2,8\}\([^|]\)/\1|\2/; # replace up to 8 | provided
# they are not preceded nor followed
# by |
s/.\(.*\)./\1/; # undo wrapping
s/|/(TAB)/g; # undo replacement
s/_p/|/g;s/_u/_/g; # undo escaping'
Если ваш sed
(например, ssed
) поддерживает регулярные выражения, подобные Perl, вы можете использовать операторы просмотра:
ssed -R 's/(?<!\(TAB\))(\(TAB\)){2,8}(?!\(TAB\))/(TAB)/g'
Или использовать perl
напрямую:
perl -lpe 's/(?<!\(TAB\))(\(TAB\)){2,8}(?!\(TAB\))/(TAB)/g'
AT&T (ast-open) sed
], с параметром -A
/ -X
поддерживается разновидность расширенных регулярных выражений, которые они называют дополненными , которые имеют оператор отрицания ( x!
) и оператор конъюнкции ( x & y
). Здесь (. {5} & (\ (TAB \))!)
соответствует последовательности из 5 символов, которая является , а не (TAB)
. Итак, с помощью этого sed
вы можете сделать что-то вроде:
sed -A '
:1
s/(^.{0,4}|.{5}&(\(TAB\))!)(\(TAB\)){2,8}(.{0,4}$|.{5}&(\(TAB\))!)/\1(TAB)\4/
t1'
Я поклонник использования Perl для подобных вещей
echo $a | grep -oP '(?<=DATE**:).*?(?=,)'
и
echo $a | grep -oP '(?<=START_TIME**:).*?(?=,)'
Используйте jq:
$ echo $a | jq '.[][0]["**DATA_DATE**"]'
"2017-03-09 00:00:00"
Поскольку jq может быть доступен не во всех дистрибутивах, и вы можете не захотеть компилировать его самостоятельно, вы можете воспользоваться преимуществами многих других языков сценариев, которые имеют поддержку JSON в своих базовых библиотеках.
Перл:
$ perl -e "use JSON::Parse 'parse_json'; my \$a = parse_json ('$(echo $a)'); print \$a->{'content'}[0]{'**DATA_DATE**'}"
2017-03-09 00:00:00
Питон:
$ python -c "import json; a=json.loads('$(echo $a)'); print(a['content'][0]['**DATA_DATE**'])"
2017-03-09 00:00:00
Рубин:
$ ruby -e "require 'json'; puts JSON.parse('$a')['content'][0]['**DATA_DATE**'];"
2017-03-09 00:00:00
Конечно, вы можете (ab )использовать стандартные инструменты *nix (GNU )для получения значений из этого конкретного примера JSON, но это действительно неудобно. Вы можете занять первую строку. Как только структура JSON изменится, ваш код будет вести себя непредсказуемо.
Как говорили другие, гораздо лучше использовать язык, (такой как perl, python или ruby ), которые имеют библиотеки для синтаксического анализа json, или специальный -целевой инструмент, который делает это как jq
... но если вы действительно хотите или должны обрабатывать данные json с помощью обычных инструментов, таких как awk
или sed
, вам сначала нужно преобразовать их в формат, ориентированный на строку -.
Почему? Потому что вы не можете надежно анализировать json только с помощью регулярных выражений, и даже если вы думаете, что преуспели, то, что у вас есть, будет невероятно хрупким и склонным к поломке даже при незначительных изменениях ожидаемого ввода.
jsonpipe
(, написанный на python ), является одним из таких инструментов, который может выполнять преобразование в формат, ориентированный на строку -. например. после исправления сломанного json в вашем примере он выдает следующий вывод:
$ jsonpipe < /tmp/nick.json
/ {}
/content []
/content/0 {}
/content/0/JOB_STATUS_ID 283739
/content/0/PROGRAM_ID 57
/content/0/STATUS "Completed"
/content/0/**DATA_DATE** "2017-03-09 00:00:00"
/content/0/**START_TIME** "2017-03-10 00:46:13"
/content/0/END_TIME "2017-03-10 00:56:40"
/content/0/TOTAL_ROWS null
/content/0/UPDATED_ROWS null
/content/0/DELETED_ROWS null
/content/0/INSERTED_ROWS null
/content/0/REF1 "NULL"
/content/0/REF2 "NULL"
/content/0/AUD_CREATE_DT "2017-03-10 00:46:13"
/content/0/AUD_CREATE_USER "JOB_CONTROL"
/content/0/AUD_MODIFY_DT "2017-03-10 00:56:40"
/content/0/AUD_MODIFY_USER "JOB_CONTROL"
/content/1 {}
/content/1/JOB_STATUS_ID 109711
/content/1/PROGRAM_ID 57
/content/1/STATUS "Completed"
/content/1/DATA_DATE "2017-01-11 00:00:00"
/content/1/START_TIME "2017-01-12 16:55:14"
/content/1/END_TIME "2017-01-12 18:54:51"
/content/1/TOTAL_ROWS null
/content/1/UPDATED_ROWS null
/content/1/DELETED_ROWS null
/content/1/INSERTED_ROWS null
/content/1/REF1 "NULL"
/content/1/REF2 "NULL"
/content/1/AUD_CREATE_DT "2017-01-12 16:55:14"
/content/1/AUD_CREATE_USER "JOB_CONTROL"
/content/1/AUD_MODIFY_DT "2017-01-12"
Это позволяет обрабатывать его с помощью стандартных утилит обработки текста. Например:
$ jsonpipe < /tmp/nick.json | \
sed -ne 's:^/content/0/\*\*DATA_DATE\*\*[[:space:]]\+::p'
"2017-03-09 00:00:00"
$ jsonpipe < /tmp/nick.json | \
awk -F'"' '/^\/content\/0\// && /DATA_DATE/ {print $2}'
2017-03-09 00:00:00
или даже что-то столь грубое, как это:
$ jsonpipe < /tmp/nick.json | grep '/0/.*DATA_DATE'
/content/0/**DATA_DATE** "2017-03-09 00:00:00"
В debian и производных системах он упакован как python-jsonpipe
и, вероятно, имеет похожее имя пакета в других дистрибутивах. Или его можно найти по адресуhttp://pypi.python.org/pypi/jsonpipe
ПРИМЕЧАНИЕ. :он поставляется с соответствующим jsonunpipe
инструментом, который вы можете использовать для преобразования этого формата, ориентированного на строку -, обратно в json -, например. после изменения его с помощью sed
или awk
или чего-то еще.