как получить параметр и значение из строки

Предполагая, что табуляция стирается после stuffв обоих этих случаях

% ls
bar     foo.txt
% whence stuff
% alias stuff=less
% zstyle ':completion:*:*:stuff:*' file-patterns '*.txt:all-files'
% stuff
bar      foo.txt

соответствующий регулятор из zshoptions(1)

COMPLETE_ALIASES
    Prevents aliases on the command line from being internally sub-
    stituted before completion is attempted. The effect is to make
    the alias a distinct command for completion purposes.

так

% setopt COMPLETE_ALIASES
% stuff foo.txt

иначе псевдоним уже что-то другое.

Чтобы проверить наличие побочных эффектов, мы должны подтвердить, что это изменение не нарушает завершение псевдонимов, для которых нет завершения или настройки стиля,

% setopt COMPLETE_ALIASES
% whence foo
% unfunction _foo
unfunction: no such hash table element: _foo
% alias foo=ls
% foo (eval):1: command not found: _foo

поэтому с установленным COMPLETE_ALIASESвам может потребоваться настроить завершение для каждого псевдонима или перечислить или иным образом включить имя псевдонима (s )в соответствующем compdef, например.

% compdef _ls foo
% foo
...

С другой стороны, я нахожу оболочки execдовольно элегантными, поскольку они, в отличие от псевдонимов оболочки, могут вызываться с помощью exec(3)или system(3)без необходимости загружать довольно большую оболочку или загрязнять то, что должно быть простой системный вызов с интерактивной настройкой оболочки.

0
26.07.2020, 16:04
4 ответа

Вы можете попробовать передать свою $infoпеременную через этот sedвызов:

echo "$info" | sed -E '/"segment\.bytes"/s/.*"(segment\.bytes)":"([^"]+)".*/\1:\2/'

Он будет искать строку с шаблоном "segment.bytes"и извлекать строку segment.bytesи строку в следующих скобках (, определенных для простоты как «что угодно, кроме "» )в группы захвата. 1 и 2, и выведите «группа захвата 1», «:» и «группа захвата 2».

(Обратите внимание, что возможность активации расширенных регулярных выражений может различаться в зависимости от вашей sedверсии. -Eтеперь является стандартом POSIX и работает с текущими версиями GNU, MacOS и BSD sed, но в случае сбоя обратитесь к справочной странице, чтобы узнать, как активировать ERE )

.

Чтобы быть более избирательным, попробуйте

sed -E '/"segment\.bytes":"[0-9]+"/s/.*"(segment\.bytes)":"([0-9]+)".*/\1:\2/'

который будет принимать только целочисленное значение как в строке поиска, так и в части захвата значения.

2
18.03.2021, 23:17

Вам не нужно звонить grepперед звонком sed.

$ echo "$info"
foo
{"version":1,"config":{"segment.bytes":"10737555","retention.bytes":"104857600"}}
bar

$ echo "$info" | sed -n 's/.*"\(segment\.bytes\)":"\([^"]*\)".*/\1:\2/p'
segment.bytes:10737555

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

$ echo "$info" |
sed -n 's/^{"version":[0-9][0-9]*,"config":{"\(segment\.bytes\)":"\([0-9][0-9]*\)","retention\.bytes":"[0-9][0-9]*"}}$/\1:\2/p'
segment.bytes:10737555

Описанное выше будет работать в любом sed.

1
18.03.2021, 23:17

Безопасным и надежным способом здесь является jqутилита:

$ echo "$info" \
| grep -F  '"segment.bytes"' \
| jq  -r '.config | "segment.bytes:" + ."segment.bytes"' 

баш:

Используя parameter substitutions, мы обрезаем левый и правый концы и извлекаем значение атрибута segment.bytes.

name="segment.bytes"
var=${info#*\"${name}\":\"}
printf "%s:%s\n" "$name"  "${var%%\"*}"'

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

$ echo "$info" \
| tr '{,}' '[\n*]' \
| grep '^"segment\.bytes"' \
| tr -d \"

Использование Perl с модулем JSON

$ echo "$line" | grep -F  '"segment.bytes"' \
| perl -MJSON -lne '$,=":";
  my $k = "segment.bytes";
  print $k, decode_json($_)->{config}{$k};
'

Если модуль JSON недоступен, вы также можете сделать это. Здесь мы сначала генерируем действительный код Perl с помощью sed, а затем воплощаем его в жизнь с помощью оператора do. Тогда объект json $j является хэш-ссылкой, из которой мы извлекаем нужные ключи.

$ echo "$info" \
| sed  \
    -e '/"segmen\.bytes"/!d'  \
    -e 'y/:/,/;s/.*/$j=&;/' \
  >./foo.json 
$ perl -I. -le '$,=":";
  my $name = "segment.bytes";
  do "foo.json" or die $!;
  print $name, $j->{config}{$name};
'

awk и sed говорят сами за себя

$ echo "$info" | grep -F segment.bytes \
| awk -F '"segment\\.bytes":"'  '
  {
    t = $2
    sub(/".*/, "", t)
    $0 = FS t
    gsub(/["\\]/, "")
  }1'
$ echo "$info" | grep -F segment.bytes \
| sed -ne '
    y/{,}/\n\n\n/
    /^"segment.bytes"/!D
    s/"//g;P
  ' 
0
18.03.2021, 23:17

Вы можете использовать ниже команду awk

echo "$info"|awk -F "," '/segment.bytes/{for(i=1;i<=NF;i++){if($i ~ /segment/){gsub("\"","",$i);print $i }}}'| sed "s/.*{//g"

выход

segment.bytes:10737555
0
18.03.2021, 23:17

Теги

Похожие вопросы