Почему команда «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 ах, да.
Муру
@ Могу я попросить вас опубликовать вывод 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. Как указал стилдрайвер в комментариях --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будет выведен цветной список файлов в соответствии с типом файла. Проблема в том, что раскрашивание происходит с использованием escape-последовательностей . Это то, 1:34mчто есть - это escape-последовательность для определенных цветов.

Основная проблема заключается в том, что синтаксический анализ lsчасто приводит к неправильным выводам и сбоям в сценариях просто потому, что lsдопускает escape-последовательности, подобные описанным ранее, и другие специальные символы. См. Эту статью для получения дополнительной информации: 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

Вы можете сделать что-то подобное с помощью shell 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в bash по умолчанию? type lsдает мне, что это псевдоним дляls --color=auto
Сергей Колодяжный
1
Да, это по умолчанию - но autoотключает цвет в трубе AFAIK. Чтобы увидеть цветовые последовательности ANSI, его необходимо изменить --color=alwaysна lsпсевдоним или lпсевдоним
steeldriver 28.12.16
О, я понимаю, что вы имеете в виду. Это очень странно.
Сергей Колодяжный
@steeldriver Итак, я попросил OP опубликовать его псевдонимы, и, видимо, то, что у них есть, а именно ls --color, не препятствует раскрашиванию (я тоже это проверял). Обновил мой ответ соответственно
Сергей Колодяжный
6

Ваши lи lsкоманды настроены как псевдонимы.

Когда вы запускаете их, выводите данные через grep "1"(используя |) каждую строку экрана, где 1появляется, с 1красным цветом.

Так как имена файлов ., .., 2и 22появляются на том же экране линии, они выводятся grepкак хорошо , но не отображаются красным цветом , который показывает grepматчи.

Это :34mescape-последовательность для цвета, который не рисует должным образом. На основании вашего пересмотренного вопроса с выводом type -a lи type -aего можно воспроизвести в моей системе. Пожалуйста , обратите внимание , вы должны изменить свой псевдоним от --colorдо --color=auto:

Цветной выход

цвет ls

WinEunuuchs2Unix
источник
Это 1:34mне искажение, это escape-последовательности, используемые для раскрашивания текста. Смотрите мой ответ на эту часть;)
Сергей Колодяжный
@Serg Спасибо. Я пересмотрел на основе OP пересмотренный вопрос с псевдонимами.
WinEunuuchs2Unix
1

В вашем испытании вы называли свой lsпсевдоним, таким образом, 1;34mи тому подобный шум, который исходит от окраски, и так как канал |получает все это на той же строке, grepсопоставляет файл 1из этой строки и, следовательно, печатает эту строку. Это то, что вы видите на экране.

Когда вы делаете подобные вещи, всегда хорошо вернуться к системной команде с 1 результатом на строку.

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

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

Примечание: метод обратной косой черты работает с каждой командой, \commandпросто вызывает системную команду без слияния.

Пилько
источник