Чому команда труби «l | grep "1" "отримати неправильний результат?


13

Як показано на малюнку, я використовую, lщоб отримати файл у поточній папці. І тоді я хочу отримати файл з номером 1, тому я використовую pipeі grep.

Але чому файл 2і 22файл з'являються? А що таке 1;34m?

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

Оновлення

Я вже псевдонім команду lу моєму zshrcфайлі.

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

І ось результат typeкоманди:

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

> $ type l
l is an alias for ls -CF

4
Не публікуйте скріншоти тексту. Скопіюйте текст тут і застосуйте форматування коду.
муру

@muru Я думаю, ти мав намір запитати пост-вихід type -a l?
WinEunuuchs2Unix

@ WinEunuuchs2Unix ах, так.
муру

@Lee, чи можу я попросити вас опублікувати вихід type lsкоманди? Ви lsбудь-яким чином змінили псевдонім?
Сергій Колодяжний

@Serg вже оновлено.
Лі

Відповіді:


27

Перш за все, те, що ви намагаєтеся зробити, l| grep <filename>це погано. Не робіть цього. Ось чому.

l команда справді псевдонім до ls -CF

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

За замовчуванням в Ubuntu bash, lsце псевдонім до ls --color=auto. Як зазначив steeldriver у коментарях --color=auto, передбачається вимкнути колоризацію. У вашому конкретному випадку у вас є alias ls="ls -alh --color"і alias l="ls -CF", що в основному і закінчується ls -alh --color -CF. Ця комбінація комутаторів все ще посилає кольоровий вихід через трубу. Наприклад:

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

Зверніть увагу на те, як .і ..каталоги мають однакові послідовності втечі.

Що це все означає

Це означає, що lбуде видано кольоровий список файлів відповідно до типу файлу. Проблема полягає в тому, що забарвлення відбувається із застосуванням послідовностей втечі . Ось що таке 1:34m- вони послідовно виходять для певних кольорів.

Основна проблема полягає в тому, що синтаксичний аналіз lsчасто призводить до неправильних результатів та катастроф у сценаріях, просто тому, що lsдозволяє виконувати послідовності втечі, як пояснено раніше, та інші спеціальні символи. Дивіться цю статтю для отримання додаткової інформації: http://mywiki.wooledge.org/ParsingLs

Що ви повинні робити:

Використовувати findкоманду:

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

Ви можете зробити щось подібне за допомогою оболонки glob та сучасної тестової [[команди:

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

Або, можливо, використовуйте python, який має набагато кращі можливості обробки імен файлів, ніж bashпоодинці

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

Якщо немає необхідності обробляти lsвисновки, простий глобус також lsможе зробити свою роботу. (Пам'ятайте, що це лише для перегляду списку файлів, а не для передачі його іншій програмі для обробки вихідного тексту)

bash-4.3$ ls *1*
1.txt

2
Я думаю, що вихід буде забарвлений лише в трубі, якщо --color=alwaysвін також буде вказаний - або як частина псевдоніма для, lабо в попередньому псевдонімі для lsсебе (замінивши за замовчуванням alias ls='ls --color=auto').
steeldriver

@steeldriver Добре, але хіба це не те, що lsв баші за замовчуванням є? type lsдає мені, що це псевдонім дляls --color=auto
Сергій Колодяжний,

1
Так, це за замовчуванням - але autoвимикає колір у трубі AFAIK. Щоб побачити колірні послідовності ANSI, він повинен бути змінений --color=always, або в lsпсевдоніма або lпсевдонім
steeldriver

О, я бачу, що ти маєш на увазі. Це дуже дивно.
Сергій Колодяжний

@steeldriver Тому я попросив ОП опублікувати його псевдоніми, і, мабуть, те, що вони мають, а саме ls --color, не перешкоджає колоризації (тестував це і я). Відповідно оновив мою відповідь
Сергій Колодяжний

6

Ваші lта lsкоманди налаштовані як псевдоніми.

Коли ви запускаєте їх, пропускаючи висновки через grep "1"(використовуючи |) кожну лінію екрана, де 1відображається, 1кольоровим кольором.

Так як імена файлів ., .., 2і 22з'являються на тому ж екрані лінії, вони виводяться grepяк добре , але не відображаються червоним кольором , який показує grepматчі.

Це :34mпослідовність виходу кольору, який не фарбується належним чином. На основі Вашого переглянутого питання з результатом роботи, type -a lі type -aвін може бути відтворений у моїй системі. Зауважте, що вам слід змінити псевдонім --colorна --color=auto:

Кольоровий вихід

колір ls


У 1:34mречі не корупція, вони екранують послідовності , використовувані для розфарбовування тексту. Дивіться мою відповідь у цій частині;)
Сергій Колодяжний

@Serg Дякую Я переглянув на основі переглянутого ОП питання з псевдонімами.
WinEunuuchs2Unix

1

Під час випробування ви називали свій lsпсевдонім, таким чином, 1;34mі подібний шум, який виникає від забарвлення, і оскільки труба |отримує все це в одній лінії, grepвідповідає файлу 1з цього рядка і, отже, друкує цей рядок. Це те, що ви бачите на екрані.

Коли ви робите подібні речі, завжди добре повернутися до системної команди з 1 результатом на рядок.

Щоб позбутися псевдонімів, просто введіть \lsі скористайтеся опцією -1для друку результатів, розділених каналами рядків.

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

Примітка: метод зворотної косої риси працює з кожною командою, \commandпросто викликує ненадійну системну команду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.