Я скопировал команду cd C:\foo\bar\
из PowerShell в Cygwin и, как ни странно, ожидал ее выполнения. Я сейчас пытаюсь запустить замену , чтобы заменить все \
с /
:
$ !!:gs/\\/\/
bash: :gs/\\/\/: substitution failed
Не уверен, почему замена мне не удалась.
Я также попробовал:
$ !!:gs/\\/q
Просто чтобы посмотреть, была ли проблема в замене. Это не. Теперь мне любопытно!
Почему я получаю "замена не удалась"?
cd 'C:\foo\bar'
!!:gs/\\/\/
работает в zsh…fc -s '\'='/' -1
работает по умолчанию в bash для Ubuntu LTS. Дайте мне знать, если он работает и под Cygwin. Я написал больше слов в ответе.!!:gs/\\/\//
. @Hastur 'sfc -s '\'='/' -1
получает ожидаемое поведение. это может быть ошибка в bash.Ответы:
косая черта также является разделителем вашей команды замены, поэтому вы должны экранировать ее как строку замены, чтобы не завершить замену раньше.
или более просто, как это предлагается в комментариях, используя что-то помимо косой черты в качестве разделителя
Но это только работает
tcsh
(оболочка обычно назначается там, где я нахожусь), я не могу заставить команду работать,bash
так как кажется, что экранирование не работает с первым аргументом:s
источник
!!:gs|\\|/
может быть немного более читабельным.:s
похоже, не является настоящим регулярным выражениемКраткий ответ: встроенная
fc
(исправить команду) Bashfc
это команда, встроенная в оболочку bash, предназначенная для редактирования и повторного выполнения команд истории.Он также присутствует в CygWin и работает на всех дистрибутивах Linux, на которых я тестировал:
Некоторые объяснения
fc
это встроенная команда bash для вывода, редактирования и повторного выполнения команд из списка истории.-1
примет последнюю команду в истории. Обратите внимание, что даже!!
определяется (читать изman bash
) как-s
заменить шаблон другим. На этот раз изhelp fc
(встроенная команда такhelp
):Хорошо, они имеют в виду
pat=rep
вместоOLD=NEW
...'\'
и'/'
.Несколько слов о том, почему вы получаете «замена не удалась»
Похоже, что для
s
модификатора (пока) не реализована подстановка символа обратной косой черты\
, то есть escape- символа . Чтобы быть уверенным, мы должны увидеть код, например, версии gnu расширения истории bash (но была указанная выше команда, чтобы получить то, что вы пытались сделать ... поэтому я считаю это ленивым ....).Некоторые заметки:
Мы склонны думать, что он будет работать каждый RegEx, с которым мы работаем
sed
, но это не гарантировано. Обратная косая черта является escape-символом расширения, и проблема здесь. Кроме того, поведение расширения связано сshopt
опциями, поэтому мы должны начать видеть в каждом конкретном случае ...Когда вы вставите строку
cd C:\Foo\Bar
в оболочку bash, она будет развернута и появится для интерпретатора какcd C:FooBar
; в этом виде он также будет храниться во$_
внутренней переменной.Если вы вместо этого вставили
cd "C:\Foo\Bar"
илиcd 'C:\Foo\Bar'
в$_
переменной вы должны найтиC:\Foo\Bar
.Поскольку расширение «История» выполняется сразу после прочтения полной строки, перед тем, как оболочка разбивает ее на слова, у вас может возникнуть соблазн начать использовать его с некоторым более или менее простым башизмом , например, с некоторой производной от (может быть, добавления
:p
или:q
,""
, разбор и тд ...)Это момент, который нужно помнить, что небезопасно начинать играть с путями и именами файлов , особенно если они приходят из буфера обмена Windows (читайте в общем на странице « Почему не анализировать
ls
?» , Это по сути связано с возможностью использовать tab, пробелы и переводы строк как правильные символы для имен файлов и каталогов ...).Более того, когда вы вставляете текст, захваченный мышью , вы также можете вставить начальный пробел. Это может помочь избежать завершения вашей команды в истории (это зависит от параметров оболочки ...). Если это так, ваша следующая
!!
команда будет неконтролируемой ... (см. Пример в другом ответе ).Это ненужный ощутимый риск .Вывод
Если это не так просто, я начинаю думать, что мы делаем что-то не так
;-)
До тошноты: небольшой эксперимент
Я включил
histverify
в оболочке тогда ...потом жму Enterи в качестве проверенного расширения нахожу
затем я нажимаю Enterснова, и это эхом
Похоже, это указывает на то, что
substitution failed
генерируется в расширении истории, обработанном до расширения Брэйс , поэтому, во- первых , и это подтверждает, чтоs
модификатор истории (еще) не обрабатывал замену\
символа как реального регулярного выражения. ..источник
Вы можете использовать,
sed
чтобы заменить и выполнить результат.Есть несколько возможных вариантов такой команды, но на моем bash работал только этот:
Символ
\\
добавляется!!
в случае, если последняя команда завершается с обратной косой чертой. Без этого оболочка запутается и попросит продолжения линии.Вы также можете добавить это как функцию bash в файл
~/.bashrc
:Вот как это работает на моем Bash на Windows:
Чтобы объяснить, как
A=
команда назначает правильное значение переменной оболочкиA
:tail
берет последние две строки из истории команд, которая дает строки, заcd \mnt\c
которыми следуетslash
сама. Частьhistory | tail -n 2
также может быть записана какhistory 2
.head
взять первую строку, котораяcd \mnt\c
cut
вырезает номер строки, предоставленнойhistory
sed
заменяет все анти-слэши на слэшиeval
выполняет содержимое переменнойA
источник
A=$(echo "!!\\" | sed 's,\\,/,g');eval $A
не работает, когда команда заканчивается обратной косой чертой. Вы вынуждены добавить пробел, например, кC:\Foo\Bar\
другому, как вы сказали, оболочка будет ожидать продолжения строки. Вы также можете нажать Enter дважды. В первом случае вы получитеC:/Foo/Bar /
(с пробелом перед/
, во втором он будет генерировать ошибку , функция работает отлично..Я не думаю, что вы можете сделать это. Вам нужно скопировать / пройти снова.
Проблема не связана с тем, что косая черта также является разделителем команды замены, так как команда замены принимает любой разделитель. Проблема заключается в замене обратной косой черты, которая уже рассматривается как простые бесполезные спуски символов справа от них.
Следовательно, когда вы вызываете команду замены, обратный слеш уже исчез из источника. Просто попробуйте повторно вызвать команду как есть (
!!
). Вместо того, чтобы печатать ту же самую команду, включаяc:\foo
, она выполнит команду без уже обработанных обратных слешей, что приведет кc:foo
.И, очевидно, вы не можете найти или заменить отсутствующий символ. Попытка сделать это вызовет ошибку.
источник
echo c:\Foo
затем!!:gs,F,\\f,
. Но подмена самого побега с обратной косой черты кажется болью.