Mengapa perintah pipa “l | grep ”1“ ”mendapatkan hasil yang salah?

13

Seperti yang diilustrasikan gambar, saya gunakan luntuk mendapatkan file di folder saat ini. Dan kemudian saya ingin mendapatkan file dengan nomor 1, jadi saya menggunakan pipedan grep.

Tetapi mengapa 2dan 22file muncul? Dan apa itu 1;34m?

$ l
./ ../ 1 11 2 22
$ l | grep "1"
1;34m./ 1;32m../ 1 11 2 22

Memperbarui

Saya sudah alias perintah ldalam zshrcfile saya .

 alias lsp="ls"
 alias ll='ls -alF'
 alias la='ls -A'
 alias l='ls -CF'
 alias ls="ls -alh --color"

Dan ini adalah hasil dari typeperintah:

>$ type ls
ls is an alias for ls -alh --color

> $ type l
l is an alias for ls -CF
Lee
sumber
4
Tolong jangan memposting tangkapan layar teks. Salin teks di sini dan terapkan pemformatan kode.
muru
@uru saya pikir Anda bermaksud untuk meminta posting output type -a l?
WinEunuuchs2Unix
@ WinEunuuchs2Unix ah, ya.
muru
@Lee, bisakah saya meminta Anda untuk mengirim output dari type lsperintah? sudahkah Anda memodifikasi lsalias dengan cara apa pun?
Sergiy Kolodyazhnyy
@Serg sudah diperbarui.
Lee

Jawaban:

27

Pertama-tama, apa yang Anda coba lakukan, l| grep <filename>itu buruk. Jangan lakukan itu. Inilah sebabnya.

l Perintah ini sebenarnya adalah alias untuk ls -CF

$ type -a l
l is aliased to `ls -CF'

Secara default di Ubuntu bash, lsadalah alias untuk ls --color=auto. Seperti yang ditunjukkan steeldriver dalam komentar --color=autoyang seharusnya mematikan pewarnaan. Dalam kasus spesifik Anda, Anda memiliki alias ls="ls -alh --color"dan alias l="ls -CF", yang pada dasarnya berakhir ls -alh --color -CF. Kombinasi sakelar khusus ini masih mengirimkan keluaran berwarna melalui pipa. Sebagai contoh:

$ ls -alh --color -CF ~/TESTDIR | cat -A                                                                                 
^[[0m^[[01;34m.^[[0m/  ^[[01;34m..^[[0m/  1.txt  2.txt  3.txt  out.txt$

Perhatikan bagaimana direktori .dan ..memiliki urutan pelarian yang sama.

Apa arti semua ini?

Ini berarti bahwa lakan menampilkan daftar file berwarna sesuai dengan jenis file. Masalahnya adalah bahwa pewarnaan terjadi dengan penggunaan urutan melarikan diri . Itulah yang terjadi 1:34m- mereka melarikan diri urutan untuk warna tertentu.

Masalah utama adalah bahwa parsing lssering menyebabkan output yang salah dan bencana dalam skrip, hanya karena lsmemungkinkan urutan melarikan diri seperti yang dijelaskan sebelumnya dan karakter khusus lainnya. Lihat artikel ini untuk info lebih lanjut: http://mywiki.wooledge.org/ParsingLs

Apa yang seharusnya Anda lakukan:

Gunakan findperintah:

bash-4.3$ ls
1.txt  2.txt  3.txt  out.txt
bash-4.3$ find . -maxdepth 1 -iname "*1*"
./1.txt

Anda dapat melakukan sesuatu seperti ini dengan shell glob dan [[perintah tes modern :

bash-4.3$ for file in * ;do if [[ "$file" =~ "1"  ]] ;then echo "$file" ;fi ; done
1.txt

Atau mungkin menggunakan python, yang memiliki kemampuan menangani nama file yang jauh lebih baik daripada bashsendirian

bash-4.3$ python -c 'import os;print [f for f in os.listdir(".") if "1" in f ]'
['1.txt']

Jika tidak perlu memproses output ls, globbing sederhana lsdapat melakukan pekerjaan juga. (Ingat, ini hanya untuk melihat daftar file, bukan untuk meneruskannya ke program lain untuk berurusan dengan teks output)

bash-4.3$ ls *1*
1.txt
Sergiy Kolodyazhnyy
sumber
2
Saya pikir output hanya akan diwarnai dalam pipa jika --color=alwaysjuga ditentukan - baik sebagai bagian dari alias untuk latau dalam alias sebelumnya untuk lsdirinya sendiri (mengganti default alias ls='ls --color=auto').
steeldriver
@steeldriver Poin bagus, tapi bukankah itu yang lsdi-bash secara default? type lsmemberi saya bahwa itu adalah alias untukls --color=auto
Sergiy Kolodyazhnyy
1
Ya itu default - tetapi automematikan warna dalam AFAIK pipa. Agar dapat melihat urutan warna ANSI, itu harus diubah menjadi --color=always, baik dalam lsalias atau lalias
steeldriver
Oh, aku mengerti maksudmu. Itu sangat aneh.
Sergiy Kolodyazhnyy
@steeldriver Jadi saya meminta OP untuk memposting aliasnya, dan ternyata apa yang mereka miliki, yaitu ls --color, tidak mencegah pewarnaan (diuji sendiri juga). Diperbarui jawaban saya sesuai
Sergiy Kolodyazhnyy
6

Perintah Anda ldan lsdiatur sebagai alias.

Ketika Anda menjalankannya, perpipkan output melalui grep "1"(menggunakan |) setiap baris layar di mana 1muncul ditampilkan, dengan 1berwarna merah.

Karena nama file ., .., 2dan 22muncul pada baris layar yang sama, mereka output dengan grepjuga tapi tidak muncul dalam warna merah yang menunjukkan greppertandingan.

Ini :34madalah urutan pelarian untuk warna yang tidak melukis dengan benar. Berdasarkan pertanyaan Anda yang telah direvisi dengan hasil type -a ldan type -adapat direproduksi di sistem saya. Harap perhatikan bahwa Anda harus mengubah alias dari --colormenjadi --color=auto:

Output warna

warna ls

WinEunuuchs2Unix
sumber
Hal- 1:34mhal tidak korupsi, mereka melarikan diri urutan yang digunakan untuk pewarnaan teks. Lihat jawaban saya di bagian itu;)
Sergiy Kolodyazhnyy
@Erg, terima kasih. Saya telah direvisi berdasarkan pertanyaan yang direvisi OP dengan alias.
WinEunuuchs2Unix
1

Dalam percobaan Anda, Anda memanggil lsalias Anda , dengan demikian 1;34msuara berisik dan serupa yang berasal dari pewarnaan, dan karena pipa |menerima semua ini pada baris yang sama, maka grepcocok dengan file 1dari garis itu dan akibatnya mencetak baris ini. Inilah yang Anda lihat di layar.

Ketika Anda melakukan hal-hal seperti itu, selalu baik untuk kembali ke perintah sistem dengan 1 hasil per baris.

Untuk menghilangkan alias ketikkan saja \ls, dan gunakan opsi -1untuk mencetak hasil yang dipisahkan oleh umpan baris.

$ \ls -1 | grep "1"
1
11

Catatan: metode backslash bekerja dengan setiap perintah, \commandcukup panggil perintah sistem yang tidak diubah.

pilko
sumber