Son komutta eğik çizgi için Ters Eğik Çizgi'yi değiştirin


10

Komutu cd C:\foo\bar\PowerShell'den Cygwin'e kopyaladım ve sillly çalışmasını bekledim. Şimdi tüm değiştirmek için bir ikame yönetmeye çalışıyorum \ile /:

$ !!:gs/\\/\/
bash: :gs/\\/\/: substitution failed

Değişikliği neden başarısız yaptığımdan emin değilim.

Ayrıca denedim:

$ !!:gs/\\/q

Değişimin sorun olup olmadığını görmek için. Değil. Şimdi merak ediyorum!

Neden "oyuncu değişikliği başarısız" alıyorum?


2
Şu anda elimde hiç cygwin yok, ama Windows yollarının çalıştığını düşündüm ... Yanicd 'C:\foo\bar'
mpy

@mpy Bu aslında çok işe yarıyor! Yedek oyuncu ile takılmadığımı bilmiyordum.
Tanner Faulkner

1
Msgstr "zsh kullanarak bir cevaba açık olur". Orijinaliniz !!:gs/\\/\/
zsh'ta

@TannerFaulkner fc -s '\'='/' -1, Ubuntu LTS varsayılan bash altında çalışır. Cygwin altında da çalışıp çalışmadığını bana bildirin. Cevaba daha fazla kelime gönderdim.
Hastur

1
genel bash davranışı burada ters eğik çizgiler yerine geçen önce kaçar gibi işlenir olduğunu düşünüyorum !!:gs/\\/\//. @ Hastur fc -s '\'='/' -1beklenen davranışı alır. bu bash'da bir hata olabilir.
Quixotic

Yanıtlar:


6

eğik çizgi aynı zamanda ikame komutunuzun sınırlayıcısıdır, bu nedenle ikameyi erken bitirmemek için ikame dizesi olarak kaçmalısınız

!!:gs/\\/\//

veya daha açık bir şekilde yorumlarda önerildiği gibi, ayırıcı olarak eğik çizgi dışında bir şey kullanarak

!!:gs|\\|/|

Ama bu sadece işe yarıyor gibi görünüyor tcsh(benim olduğum yerde yaygın olarak atanan kabuk), bashkaçmak gibi göründüğü için çalışmaya emredemiyorum.:s


Sevinç yok :( Aynı hata i.imgur.com/QFQR0xF.png
Tanner Faulkner

1
Sadece bir açıklama: !!:gs|\\|/biraz daha okunabilir olabilir.
mpy

1
Ben bash çalışmak için alamadım. İlk arg :sdoent gerçek regex gibi görünüyor
sabitlendikten

4

Kısa cevap: bash yerleşiği fc(fix komutu)

fcbash kabuğunda yerleşik olan, geçmişin komutlarını düzenlemek ve yeniden çalıştırmak için yapılmış komuttur .
Öyle çok CygWin üzerinde mevcut ve ben test edildiği tüm Linux dağıtımlarında çalışır:

fc  -s '\'='/' -1

Bazı açıklamalar

  • fcgeçmiş listesindeki komutları listelemek veya düzenlemek ve yeniden çalıştırmak için bash yerleşik komutudur .
  • -1tarihteki son komutu alacaktır. Even !!öğesinin şu şekilde tanımlandığını (okundu man bash)

    !! Refer to the previous command. This is a synonym for! -1 '.

  • -sbir kalıbı başka bir kalıba koymak. Bu kez help fc(yerleşik komut böylece help):

    `Fc -s [pat = rep ...] [komut] 'biçiminde, OLD = NEW ikamesi yapıldıktan sonra COMMAND yeniden yürütülür.

    Tamam pat=repbunun yerine OLD=NEW...

  • Desenler kabuk tarafından okunacaktır, bu yüzden onları alıntı ile korumalıyız: '\'ve '/'.

Neden "ikame başarısız oldu" hakkında bazı kelimeler

O için görünüyor s değiştirici değil (henüz) ters eğik çizgi karakterinin ikame uygulanan \kaçış biridir. Emin olmak için, örneğin bash geçmişi genişlemesinin gnu sürümünün kodunu görmeliyiz (ama yapmaya çalıştığınız şeyi elde etmek için yukarıdaki komut vardı ... bu yüzden tembel alıyorum ....).

Bazı notlar:

  1. Birlikte çalıştığımız her RegEx'in işe yarayacağını düşünüyoruz sed, ancak garanti edilmiyor. Ters eğik çizgi genişlemenin kaçış karakteri ve sorun burada. Dahası, genişlemenin davranışı shoptseçeneklerle ilgilidir, bu yüzden duruma göre görmeye başlamalıyız ...

  2. cd C:\Foo\BarDizeyi bash kabuğunuza yapıştırdığınızda genişletilir ve yorumlayıcı için cd C:FooBar; bu formda da $_dahili değişkende saklanacaktır .
    Bunun yerine yapıştırılmış cd "C:\Foo\Bar"veya değişken cd 'C:\Foo\Bar'içinde $_bulmalısınız C:\Foo\Bar.
    Geçmiş genişleme tam bir çizgi okunduktan sonra hemen gerçekleştiği için, kelimelere kabuk sonları onu önce, bazı ile kullanmak başlamak cazip olabilir bashism belki ekleyerek (bazı türev ile, örneğin daha fazla veya daha az düz, :pya da :q, "", ayrıştırma vb.)

    !!:0 ${_//\\/\/}

    Bu güvenli olmadığını hatırlamak andır başlatmak için yolu ve oynamak için dosya adları onlar sayfa genel olarak okunan (windows panodan gelip, özellikle eğer Neden değil ayrıştırmak ls? , Aslında kullanım sekmesine imkanı ile ilgilidir boşluklar ve satır başlıkları dosya adları ve dizin adları için doğru karakterler olarak ...).
    Ayrıca , fare ile yakalanan bir metni yapıştırdığınızda, önde gelen bir alanı da yapıştırabilirsiniz. Bu, komutunuzun geçmişte bitmesini önleyebilir (kabuk seçeneklerine bağlıdır ...). Eğer öyleyse aşağıdakiler !!kontrollü olmayan bir komut olacaktır ... ( başka bir cevaptaki örneğe bakınız ).Bu gereksiz bir somut risktir .

Sonuç

Geçmiş genişletmeleri , geçmiş listesinden sözcükleri giriş akışına ekleyerek komutları tekrar etmeyi, bağımsız değişkenleri bir önceki komuta geçerli giriş satırına eklemeyi veya önceki komutlardaki hataları hızla düzeltmeyi kolaylaştırır .

Kolay değilse yanlış bir şey yaptığımızı düşünmeye başlarım ;-)


Reklam nauseam: küçük bir deneme

histverifyKabukta etkinleştirdim o zaman ...

shopt -s histverify
echo C:\Foo\Bar
!!:s|C|D| {1,2}A

sonra basın Enterve doğrulanmış genişleme olarak buldum

echo D:\Foo\Bar {1,2}A

sonra Entertekrar basıyorum ve yankılanıyor

D:FooBar 1A 2A

Bu substitution failed, Brace genişlemesinden önce işlenen geçmiş genişlemesinde üretildiğini gösterir , bu yüzden her şeyden önce , starih değiştiricinin \karakterin yerine gerçek regex olarak işlenmediğini (henüz) işlemediğini doğrulamaktadır . ..


2

sedSonucu değiştirmek ve yürütmek için kullanabilirsiniz .

Böyle bir komut için birkaç olası varyant vardır, ancak bashımda sadece bu işe yaradı:

A=$(echo "!!\\" | sed 's,\\,/,g');eval $A

\\Eklenir !!ters eğik çizgi sonlandırılmış son komut durumda olduğunu. Onsuz, kabuk karışacak ve hattın devamını isteyecek.

Bunu dosyaya bash işlevi olarak da ekleyebilirsiniz ~/.bashrc:

function slash {
   A=$(history | tail -n 2 | head -n 1 | cut -c 8- | sed 's,\\,/,g')
   eval $A
}

Bu, Windows'taki Bash'te şu şekilde çalışır:

darbe

A=Komutun kabuk değişkenine doğru değeri nasıl atadığını açıklamak için A:

  • tailkomut satırından son iki satırı cd \mnt\cizler ve bu satırdan sonra gelen satırları slashkendisi verir. Parçası olarak history | tail -n 2da yazılabilir history 2.
  • head ilk satırı al cd \mnt\c
  • cut tarafından verilen satır numarasını keser history
  • sed tüm eğik çizgileri eğik çizgilerle değiştirir
  • eval değişkenin içeriğini yürütür A

Selam Harry. A=$(echo "!!\\" | sed 's,\\,/,g');eval $AKomut bir ters eğik çizgi ile sonlandırıldığında GNU bash sürüm 4.3.11 (1) 'de çalışmadığını söylediğim için üzgünüm . Bir boşluk eklemeye zorlanırsınız, örneğin C:\Foo\Bar\ , dediğin gibi, kabuk çizginin devam etmesini bekleyecektir. Enter tuşuna iki kez de basabilirsiniz. İlk durumda elde edersiniz C:/Foo/Bar /(öncesinde boşluk olan /; ikincisinde bir hata oluşturur. Fonksiyon iyi çalışır.
Hastur

İşlevi yazdım çünkü (1) Kullanımı çok daha kolay ve (2) Tek astar uygulamaya çok fazla bağlı görünüyordu.
harrymc

-1

Bunu yapabileceğini sanmıyorum. Tekrar kopyalamanız / yapıştırmanız gerekiyor.

Sorun, ikame komut ayırıcısını da eğik çizgi ile ilgili değildir, çünkü ikame komutu herhangi bir ayırıcıyı kabul eder. Mesele, zaten sağlarında karakterin basit yararsız kaçışları olarak muamele edilmiş olan ikame edilecek ters eğik çizgilerle ilgilidir.

Bu nedenle, substitute komutunu çağırdığınızda, ters eğik çizgi zaten kaynaktan yok olur. Sadece komutu olduğu gibi tekrar aramayı deneyin ( !!). Tam olarak da dahil olmak üzere aynı komutu yazdırmak yerine c:\foo, sonuçta zaten işlenmiş ters eğik çizgiler eksi komutunu yürütür c:foo.

Ve açıkçası eksik bir karakteri bulamaz veya değiştiremezsiniz. Bunu yapmaya çalışmak bir hataya neden olur.


1
İyi. Bu test gerçekten işe yaradığından, nihayet yanlıştır: echo c:\Fooarkasından !!:gs,F,\\f,. Ancak ters eğik çizgi kaçışının yerini almak bir acı gibi görünüyor.
A. Loiseau
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.