sed удаление комментариев в строке

Я думаю, вы могли бы добавить компоненты $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

1
04.08.2017, 22:12
4 ответа

С использованием 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*(//|#)).*$::заменяется пустой строкой, если ниже видны совпадения.
    1. \s\{1,\}(//|#):любые строки, за которыми следует //или(|)#с одним или несколькими пробелами -перед этим, это сохранит ссылки, такие какhttps://domain(спасибо, @Phillippos указал на это)
    2. или|^\s*(//|#):любые строки начинаются с пробелов -, за которыми следует //или#
    3. .*$соответствует элементу выше элемента 1 или элементу 2 и всему после этого до конца строки.*$
    4. /^$/d:удаляет пустые строки. если вы хотите удалить строки, содержащие пробелы -, также замените их на /^\s*$/d.
0
27.01.2020, 23:13
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

То есть часть подстановки говорит: «В первом пробеле -косая черта -косая черта, с которой мы сталкиваемся, удаляет ее и все, что следует за ней, оставляя любой предшествующий текст в покое».

2
27.01.2020, 23:13

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 )).

6
27.01.2020, 23:13

Если вы хотите удалить комментарии из исходного файла, вы можете попробовать мой инструмент comcat. Последняя сборка за одну ночь доступна на GitHub .

  • Он может отображать только комментарии или все, кроме комментариев.
  • Это очень молодой проект, так что ждите багов.

Я понимаю, что это вопрос о sed. Если вы не находите этот ответ полезным, его можно удалить.

Отказ от ответственности:Я являюсь сопровождающим comcat.

0
27.01.2020, 23:13

Теги

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