Я думаю, вы могли бы добавить компоненты $PWD
в список завершения cd
, хотя для этого, похоже, потребуется возиться с _cd
; то есть настроенная версия _cd
должна появиться первой в $fpath
.
% cd && mkdir zcomp
% cp $fpath[-1]/_cd zcomp
% fpath=(~/zcomp $fapth)
Затем вверху ~/zcomp/_cd
добавьте функцию
_our_pwd() {
_values ourpwd ${(ps:/:)PWD}
}
, а затем непосредственно перед строкой _alternative
добавьте то, что она возвращает, в список альтернатив
...
alt=("$service-options:$service option:_cd_options" "$alt[@]")
fi
alt=(ourpwd:pwd:_our_pwd "$alt[@]")
_alternative "$alt[@]" && ret=0
return ret
...
. ] хотя это всегда будет добавлять компоненты pwd
к завершениям cd
:
% cd
Users jdoe Applications/ Desktop/ Documents/ Downloads/ Library/
...
с дополнительной логикой вы можете добавлять компоненты $PWD
только тогда, когда уже есть второй аргумент присутствует вместо всегда.
Однако! Это всегда портит завершение cd
и требует, чтобы мы исправили восходящее завершение _cd
. Другим вариантом может быть создание нового имени для функции с двумя аргументами cd
, возможно называемой cdsub
, и иметь только завершение компонентов PWD
. появиться для этого. Добавьте это в ~/.zshrc
function cdsub { builtin cd "$@" }
А затем завершение _cd
для _cdsub
для размещения где-то в $fpath
:
#compdef cdsub
#
# Modified version of _cd from ZSH 5.3.1 with specific support for the
# `cd old new` form whereby PWD elements are provided for completion.
_cd_options() {
_arguments -s \
'-q[quiet, no output or use of hooks]' \
'-s[refuse to use paths with symlinks]' \
'(-P)-L[retain symbolic links ignoring CHASE_LINKS]' \
'(-L)-P[resolve symbolic links as CHASE_LINKS]'
}
setopt localoptions nonomatch
local expl ret=1 curarg
integer argstart=2 noopts
if (( CURRENT > 1 )); then
# if not in command position, may have options.
# Careful: -<-> is not an option.
while [[ $words[$argstart] = -* && argstart -lt CURRENT ]]; do
curarg=$words[$argstart]
[[ $curarg = -<-> ]] && break
(( argstart++ ))
[[ $curarg = -- ]] && noopts=1 && break
done
fi
if [[ CURRENT -eq $((argstart+1)) ]]; then
# cd old new: look for old in $PWD and see what can replace it
local rep
# Get possible completions using word in position 2
rep=(${~PWD/$words[$argstart]/*}~$PWD(-/))
# Now remove all the common parts of $PWD and the completions from this
rep=(${${rep#${PWD%%$words[$argstart]*}}%${PWD#*$words[$argstart]}})
(( $#rep )) && _wanted -C replacement strings expl replacement compadd -a rep
else
_values ourpwd ${(ps:/:)PWD} && ret=0
return ret
fi
С использованием sed
для сохранения ссылок и комментариев обоих типов //
и#
:
sed -E -e 's:(\s\{1,\}(//|#)|^\s*(//|#)).*$::; /^$/d' infile.txt
Или если комментарии только с //
, то:
sed -E -e 's:(\s\{1,\}//||^\s*//).*$::; /^$/d' infile.txt
А если ссылки нет или вы не против ссылок, то будет еще короче:
sed -E -e 's:\s*//.*$::; /^$/d' infile.txt
s:(\s\{1,\}(//|#)|^\s*(//|#)).*$::
заменяется пустой строкой, если ниже видны совпадения. \s\{1,\}(//|#)
:любые строки, за которыми следует //
или(|
)#
с одним или несколькими пробелами -перед этим, это сохранит ссылки, такие какhttps://domain
(спасибо, @Phillippos указал на это)|^\s*(//|#)
:любые строки начинаются с пробелов -, за которыми следует //
или#
.*$
соответствует элементу выше элемента 1 или элементу 2 и всему после этого до конца строки.*$
/^$/d
:удаляет пустые строки. если вы хотите удалить строки, содержащие пробелы -, также замените их на /^\s*$/d
. sed -e '/^\/\//d' -e 's@\(.*\)[[:blank:]]\{1,\}//.*@\1@' your_file
Эта команда sed удаляет строки, начинающиеся с комментария, а для встроенных комментариев она удаляет все, начиная с пробела, отделяющего код от комментария, до конца строки. Это POSIX (без использования расширений GNU )и, согласно исходному примеру OP и для простоты чтения, эта версия поддерживает только //
комментарии (, подробнее об этом ниже ).
Детали
Этот вызов sed
включает две команды sed :«удалить при совпадении с шаблоном» и замену.
Первый — /^\/\//d
. Шаблон ^\/\/
соответствует строкам, начинающимся с двух косых черт (, например. "// foo bar" ). Такие строки удаляются и сразу вставляется следующая строка (т.е. подстановка пропускается ).
Шаблон в замене \(.*\)[[:blank:]]\{1,\}//.*
. Примечание. :Я использую @
в качестве разделителя, чтобы избежать экранирования некоторых символов, которые требуются для разделителя /
.
\(
...\)
- все, что соответствует внутри, доступно в качестве обратной ссылки .*
-соответствует 0 или более символов (что угодно, кроме новой строки ); в разделе подстановки мы можем вернуться к тому, что соответствует здесь, из-за окружения \(
и \)
. [[:blank:]]
-пробел \{1,\}
-соответствует одному или нескольким предшествующим элементам([[:blank:]]
в данном случае)//
-соответствует двум косым чертам (, то есть началу комментария).*
-То же, что и выше, за исключением того, что недоступно в качестве обратной ссылки Часть подстановки — это просто \1
, которая говорит заменить все, что мы сопоставили с первой обратной ссылкой, то есть .*
, которая предшествовала [[:blank:]]
.
Таким образом, это работает именно так, как я описал :для встроенных комментариев удалить все, начиная с пробела, отделяющего код от комментария, до конца строки.
' #' Комментарии
В GNU sed добавление обработки комментариев #
— это всего лишь вопрос замены //
чередованием(#|//)
(или необходимости экранирования\(#\|\/\/\)
). Однако способ POSIX гораздо более подробный, потому что чередование не поддерживается. Очевидно, вы могли бы переборщить, повторив существующие команды sed с версиями для #
. Еще лучше, что уже опубликован ответ, который показывает более чистый способ сделать это. В любом случае я не буду повторять решение здесь.
РЕДАКТИРОВАТЬ:
Вернувшись к этому спустя много времени, я понял, что замена более сложна, чем должна быть, и, как указано в комментариях, не улавливает некоторые угловые случаи, кроме (, например. "что-то // foo // bar".. удалено только "// bar" ).
Думаю, это все, что нам нужно...
sed -e '/^\/\//d' -e 's@[[:blank:]]\{1,\}//.*@@' your_file
То есть часть подстановки говорит: «В первом пробеле -косая черта -косая черта, с которой мы сталкиваемся, удаляет ее и все, что следует за ней, оставляя любой предшествующий текст в покое».
POSIX, вы бы сделали:
sed '
s|[[:blank:]]*//.*||; # remove //comments
s|[[:blank:]]*#.*||; # remove #comments
t prune
b
:prune
/./!d; # remove empty lines, but only those that
# become empty as a result of comment stripping'
Что с помощью GNU sed
мы можем сократить до:
sed -E 's@[[:blank:]]*(//|#).*@@;T;/./!d'
Обратите внимание, что он с радостью удалит #things
и //things
, которые не являются комментариями, как в:
const url = 'http://stackexchange.com';
x = "foo#bar";
Чтобы игнорировать #
, //
внутри кавычек, вы можете сделать:
perl -ne 'if (/./) {
s{\s*(?://|#).*|("(?:\\.|[^"])*"|'"'(?:\\\\.|[^'])*'"'|.)}{$1}g;
print if /./} else {print}'
На входе типа:
#blah
// testies one
const testies = 'two';
console.log(testies) // three
const url = 'http://stackexchange.com';
x = "not#a comment";
y = "foo\"bar" # comment
y = 'foo\'bar' # it's a comment
Дает:
const testies = 'two';
console.log(testies)
const url = 'http://stackexchange.com';
x = "not#a comment";
y = "foo\"bar"
y = 'foo\'bar'
(возможно, вам придется адаптироваться к реальному языку этих файлов (Я не знаю, поддерживает ли JavaScript #
в качестве комментария, за исключением, может быть, первой строки, начинающейся с #!
в node.js )).
Если вы хотите удалить комментарии из исходного файла, вы можете попробовать мой инструмент comcat
. Последняя сборка за одну ночь доступна на GitHub .
Я понимаю, что это вопрос о sed
. Если вы не находите этот ответ полезным, его можно удалить.
Отказ от ответственности:Я являюсь сопровождающим comcat.