Zsh son çalıştırma programının standartlarına erişebilir mi?


16

Yolları bulmak için sık sık findya da kullanıyorum locate.

(~) locate foobar.mmpz
/home/progo/lmms/projects/foobar.mmpz

Bir sonraki adım genellikle dosyaları açmak veya başka şekilde işlemektir. Yukarıdaki gibi mutlu bir durumda, bunu yapabilirim:

(~) ls `!!`
ls `locate foobar.mmpz`
/home/progo/lmms/projects/foobar.mmpz

Ancak, bazıları yol ya da bu tür bir şey olmayabilecek çok sayıda çıktı hattı olduğunda kimse çok mutlu değildir. Ayrıca, potansiyel olarak savurgan emirleri yeniden çalıştırmak da o kadar zarif değil.

Daha sonra manipülasyon için stdout'u bir dizide saklamak için zsh'yi bağlamanın bir yolu var mı? Sonuçta, akışları kullanıcıya yönlendirmek kabuğun işidir. İlk N ve son N çizgilerini daha sonra kullanmak için bir değişkende saklayabileceğini düşünüyorum, $?diğerleri ve diğerleri.

Tamam, bu çok güzel: /unix//a/59704/5674 . Şimdi her çalışma satırından sonra bu tür yakalama teçhizat zsh know-how (ve kod zsh için taşıma) hakkında soruyorum.


Akışı kullanıcıya yeniden yönlendirmek kabuğun işi değildir. Uygulamalar çıkışlarını terminal aygıtına yazar, kabuk buna dahil değildir.
Stéphane Chazelas

@StephaneChazelas, ancak akışları kullanıcının isteklerine göre akışları dosyalara yönlendirmek işin meselesidir. Ayrıca stdout'tan ayırmak için kırmızı renk stderr'i zsh için tarifler de vardır. Bence bu kabuğun akıştaki rolünü gösteriyor.
nperson325681

Evet, screenveya veya scriptprecmd ve preexec kancalarını kullanarak yapabilirsiniz .
Stéphane Chazelas

Yanıtlar:


7

Çoğu terminal öykünücüsünde ekrandan çıktı alma özelliği yoktur. Uygulamanın zor olacağını belirten xterm (“referans” terminal emülatörü) yazarını hatırlıyorum. Bu mümkün olsa bile, kabuk son istemin nerede olduğunu takip etmek zorunda kalacaktı.

Bu nedenle, fare ile xterm veya Ekrandaki klavye ile kopya yapıştırma gibi terminale özgü, manuel bir mekanizma kullanmadığınız sürece komutu tekrar çalıştırmak zorunda kalmazsınız.

Kabuğun komutların çıktısını otomatik olarak yakalaması son derece kullanışsız olacaktır, çünkü karmaşık terminali olan komutlar ile kullanıcı etkileşimleri arasında yazdırılabilir karakterler çıkaran komutlar arasında ayrım yapamaz.

Komutu yeniden çalıştırabilir ve çıktısını yakalayabilirsiniz. Her birini yapmanın çeşitli yolları vardır. Komutu yeniden çalıştırmak için şunları kullanabilirsiniz:

  • !! tarih değiştirme - yazmak için en uygun;
  • fc -e -, bir işlevde kullanılabilir.

Çıkışı yakalamak için komut ikamesini veya aşağıdakine benzer bir işlevi kullanabilirsiniz:

K () {
  lines=("${(f@)$(cat)}")
}
!! |K

Bu, linesdiziyi içine alınan komutun çıktısına ayarlar .


Öyle olsun. Şimdi, tamamen otomatik bir yaklaşımın çok zor olduğunu, ikinci en iyi şeyin Ksizinki gibi bir şey olduğunu iyi anlarımın farkındayım .
nperson325681

3

İşte çıktı değişkeninin son satırını denilen bir değişkene koyacak bir şeyin ilk kesimi $lastline.

precmd () {                                                                                                                                                                                                        
    exec 2>&- >&-
    lastline=$(tail -1 ~/.command.out) 
    sleep 0.1   # TODO: synchronize better
    exec > /dev/tty 2>&1
}

preexec() {
    exec > >(tee ~/.command.out&)
}

Bu, preexecçalıştırmak için zsh'ın kancasını kullanırexectee , komutun stdout'unun bir kopyasını saklamak için birlikte kullanır, ardından precmddepolanan çıktıyı okumak ve stdout'u istemi göstermek için yalnızca terminal olarak geri yüklemek için kullanır .

Ama yine de biraz çalışmaya ihtiyacı var. Örneğin, stdout artık bir terminal olmadığından,vimless olmadığından ve düzgün çalışmıyor.

Bu sorularda bazı yararlı ilgili bilgiler vardır:


Evet, belki de% 100 otomatik bir yaklaşım işe yaramayacaktır. Kodda birçok execçağrı var, komut birden çok kez çalışıyor mu yoksa özel anlambilimde yakalandım mı?
nperson325681

execbir program adı olmadan sadece yönlendirmeleri ayarlar.
Mikel

2

Bunu, sonuçlarınızı teesadece bir dosyaya kaydederek aynı anda görüntüleyen sonuçlara yönlendirerek yapabilirsiniz.

Böylece, örneğin, çıktılarınızı normal gibi gösteren ancak aynı zamanda dosyaya kaydeden bunu yapabilirsiniz /tmp/it

locate foobar.mmpz | tee /tmp/it

sonra bu dosyayı kedi ve şeyler seçmek için grep, örneğin

cat /tmp/it | grep progo | grep lms

sonra kullanmak için, bunu yapabilirsin:

vi $(!!)


2

Bu yarı pişmiş çözümü buldum:

alias -g ___='"$(eval "$(fc -ln -1)" | tail -n 1)"'

Bu ___, komut satırındaki herhangi bir noktaya yazmanıza olanak tanır . Önceki komut yeniden çalıştırılacak ve ___yerine çıktısının son satırı yerleştirilecektir. Örnek kullanım:

$ touch foo bar baz
$ ls -1
bar
baz
foo
$ vim ___

Son komut, değerine genişletilecek vim foo.

Bunun bazı keskin kenarları var!

  • ___Bir komuta eklerseniz, ancak önceki komut a'yı da içeriyorsa ___, kabuk bir süre garip bir durumda asılı kalır. Ctrl- ile hemen bu durumdan çıkabilirsiniz C.

  • Ayrıca , olduğu gibi ve diğer yapıları Tabgenişletmek için tuşuna basamazsınız.___!$

  • Bazı komutlar “normal” olarak çalıştırıldıklarında ve bir boruya bağlandıklarında farklı çıktılar görüntüler. ( lsVe ls | catkomutunun çıktısını karşılaştırın .) Tarafından tetiklenen komut ___bunlardan biriyse, beklediğinizden farklı bir komut çalıştırabilirsiniz.

  • Ve elbette, sonuncusundan başka bir çıktı hattıyla bir şey yapmak istiyorsanız, bu size yardımcı olmaz.

Adı seçtim, ___çünkü bu bir komut satırına hiçbir zaman bir argüman olarak bile dahil etmek istemediğim bir şey. Farklı bir ad seçebilirsiniz, ancak yanlışlıkla sizin için genişletilebilecek bir şey seçmemeye dikkat edin.

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.