Предполагая, что табуляция стирается после 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)
без необходимости загружать довольно большую оболочку или загрязнять то, что должно быть простой системный вызов с интерактивной настройкой оболочки.
Вы можете попробовать передать свою $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/'
который будет принимать только целочисленное значение как в строке поиска, так и в части захвата значения.
Вам не нужно звонить 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.
Безопасным и надежным способом здесь является 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
'
Вы можете использовать ниже команду 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