Skopiowałem polecenie cd C:\foo\bar\
z PowerShell do Cygwin i głupio spodziewałem się, że zostanie wykonane. Jestem teraz próbuje uruchomić podstawienie wymienić wszystkich \
z /
:
$ !!:gs/\\/\/
bash: :gs/\\/\/: substitution failed
Nie jestem pewien, dlaczego nie udało mi się zastąpić.
Próbowałem także:
$ !!:gs/\\/q
Żeby sprawdzić, czy problem stanowi zamiennik. To nie jest. Teraz jestem ciekawa!
Dlaczego dostaję komunikat „Nieudana zamiana”?
cd 'C:\foo\bar'
!!:gs/\\/\/
działa w zsh…fc -s '\'='/' -1
działa w domyślnej wersji bash Ubuntu LTS. Daj mi znać, jeśli działa również pod Cygwin. W odpowiedzi umieściłem więcej słów.!!:gs/\\/\//
. @Hasturfc -s '\'='/' -1
dostaje oczekiwane zachowanie. to może być błąd w bashu.Odpowiedzi:
ukośnik jest również ogranicznikiem polecenia zastępczego, więc musisz go uciec jako ciąg zastępczy, aby nie zakończyć wcześniejszego podstawiania
lub bardziej wyraźnie, jak sugerowano w komentarzach, używając czegoś oprócz slash jako separatora
Ale to wydaje się działać tylko
tcsh
(powłoka zwykle przypisywana tam, gdzie jestem), nie mogę uzyskać polecenia do działania,bash
ponieważ wydaje się, że ucieczka nie działa w przypadku pierwszego argumentu:s
źródło
!!:gs|\\|/
może być trochę bardziej czytelna.:s
nie wydaje się być prawdziwym wyrażeniem regularnymKrótka odpowiedź: wbudowane
fc
(polecenie naprawy) bashfc
to polecenie wbudowane w powłokę bash, przeznaczone do edycji i ponownego uruchamiania poleceń historii.Jest także obecny w CygWin i działa na wszystkich dystrybucjach Linuksa, na których testowałem:
Kilka wyjaśnień
fc
jest wbudowanym poleceniem bash do wyświetlania lub edycji i ponownego uruchamiania poleceń z listy historii.-1
podejmie ostatnie polecenie w historii. Zauważ, że nawet!!
jest zdefiniowane (odczytywane zman bash
) jako-s
aby zastąpić wzór innym. Tym razem odhelp fc
(wbudowane polecenie więchelp
):Ok, mają na myśli
pat=rep
zamiastOLD=NEW
...'\'
i'/'
.Kilka słów więcej o tym, dlaczego otrzymujesz „podstawienie nie powiodło się”
Wydaje się, że dla
s
modyfikatora nie jest (jeszcze) zaimplementowane podstawienie znaku odwrotnego ukośnika\
, to znaczy ucieczki. Dla pewności powinniśmy zobaczyć kod, na przykład, wersji gnu rozszerzenia historii bash (ale było powyższe polecenie, aby uzyskać to, co próbujesz zrobić ... więc leniwie to robię ...).Niektóre uwagi:
Jesteśmy przekonani, że będzie działać z każdym RegEx, z którym współpracujemy
sed
, ale nie jest to gwarantowane. Odwrotny ukośnik jest znakiem ucieczki rozszerzenia i problem jest tutaj. Ponadto zachowanie rozszerzenia jest powiązane zshopt
opcjami, więc powinniśmy zacząć widzieć przypadek po przypadku ...Po wklejeniu łańcucha
cd C:\Foo\Bar
do powłoki bash zostanie on rozwinięty i pojawi się dla interpretera jakocd C:FooBar
; w tej formie będzie również przechowywany w$_
zmiennej wewnętrznej.Jeśli zamiast tego wkleiłeś
cd "C:\Foo\Bar"
lubcd 'C:\Foo\Bar'
w$_
zmiennej powinieneś znaleźćC:\Foo\Bar
.Ponieważ ekspansja Historii jest wykonywana natychmiast po przeczytaniu pełnego wiersza, zanim powłoka podzieli go na słowa, możesz mieć pokusę, aby zacząć używać go z mniej lub bardziej oczywistym bazizmem , np. Z pewną pochodną (być może dodając
:p
lub:q
,""
, parsowanie i tak dalej ...)To jest moment, aby pamiętać, że nie jest bezpiecznie zaczynać grę ścieżką i nazwami plików , szczególnie jeśli pochodzą one ze schowka systemu Windows (przeczytaj ogólnie stronę Dlaczego nie parsować
ls
?) , Jest to zasadniczo związane z możliwością użycia tabulacji, spacje i znaki nowej linii jako poprawne znaki dla nazw plików i katalogów ...).Ponadto po wklejeniu tekstu przechwyconego myszą możesz również wkleić wiodące miejsce. Dzięki temu twoje polecenie zakończy się w historii (zależy to od opcji powłoki ...). Jeśli tak, twoje
!!
obserwacje będą niekontrolowanym poleceniem ... (zobacz przykład w innej odpowiedzi ).Jest to niepotrzebne namacalne ryzyko .Wniosek
Jeśli nie jest to łatwe, zaczynam myśleć, że robimy coś złego
;-)
Ad nauseam: mały eksperyment
Włączyłem wtedy
histverify
w powłoce ...następnie naciskam Enteri jako zweryfikowane rozszerzenie znajduję
potem Enterponownie naciskam i echo
To wydaje się wskazywać, że
substitution failed
jest generowane w rozszerzeniu historii przetworzonym przed rozszerzeniem Brace , więc przede wszystkim i wydaje się potwierdzać, żes
modyfikator historii nie (jeszcze) przetworzył podstawienia\
znaku jako prawdziwego wyrażenia regularnego. ..źródło
Możesz użyć,
sed
aby zastąpić i wykonać wynik.Istnieje kilka możliwych wariantów takiego polecenia, ale na moim bashu tylko ten działał:
\\
Dodaje się do!!
to w przypadku ostatniego polecenia zakończona lewym ukośnikiem. Bez tego pocisk zostanie zdezorientowany i poprosi o kontynuację linii.Możesz również dodać to jako funkcję bash w pliku
~/.bashrc
:Oto jak to działa na moim Bash w systemie Windows:
Aby wyjaśnić, w jaki sposób
A=
polecenie przypisuje odpowiednią wartość do zmiennej powłokiA
:tail
trwa dwa ostatnie wiersze z historii poleceń, co daje wierszecd \mnt\c
następnieslash
siebie. Częśćhistory | tail -n 2
można również zapisać jakohistory 2
.head
weź pierwszą linię, która jestcd \mnt\c
cut
wycina numer linii podany przezhistory
sed
zastępuje wszystkie anti-ukośniki ukośnikamieval
wykonuje zawartość zmiennejA
źródło
A=$(echo "!!\\" | sed 's,\\,/,g');eval $A
nie działa, gdy polecenie zakończyło się odwrotnym ukośnikiem. Jesteś zmuszony dodać spację, np. DoC:\Foo\Bar\
innej, jak powiedziałeś, powłoka będzie czekać na kontynuację linii. Możesz także nacisnąć dwukrotnie klawisz Enter. W pierwszym przypadku otrzymujeszC:/Foo/Bar /
(ze spacją przed/
; w drugim generuje błąd. Funkcja działa dobrze.Nie sądzę, że możesz to zrobić. Musisz ponownie skopiować / wkleić.
Problem nie jest związany z ukośnikiem jako separatorem polecenia zastępczego, ponieważ polecenie zastępcze akceptuje dowolny separator. Chodzi o zamianę ukośników, które zostały już potraktowane jako proste bezużyteczne ucieczki postaci po ich prawej stronie.
Dlatego po wywołaniu polecenia zastępczego ukośnik zniknął już ze źródła. Spróbuj ponownie wywołać polecenie tak, jak jest (
!!
). Zamiast wypisać dokładnie to samo polecenie, w tym poleceniec:\foo
, wykona polecenie minus już przetworzone ukośniki odwrotne, w wyniku czegoc:foo
.I oczywiście nie możesz znaleźć ani zastąpić brakującej postaci. Próba zrobienia tego spowoduje błąd.
źródło
echo c:\Foo
następuje!!:gs,F,\\f,
. Ale samo zastąpienie odwrotnym ukośnikiem wydaje się być bólem.