Как использовать raku-e и -n с несколькими глобусами файлов

#command-line-arguments #glob #raku #command-line-tool

Вопрос:

Я хотел бы сделать следующее в raku на Windows

 raku -n -e ".say if /mydatabegin/;" *.file
 

Не удалось открыть файл C:..*.файл: Неверный аргумент

Глобус не интерпретируется как глобус. Я предполагаю, что это потому, что Windows требует, чтобы ваши программы выполняли глобализацию самостоятельно? Итак, есть ли директива или функция предварительной обработки, или даже переключатель, который я мог пропустить, или перенаправление, или что-то, что позволяет расширить глобус, сохраняя при этом простоту переключателей-n (или-p) и-e?

Очевидно, что я могу изменить его на полную программу, удалив-n (или-p), просто используя-e, чтобы указать main, и зациклившись на результатах глобуса. Но мне действительно нравится-н.

пс. Я буквально только учу раку и был удивлен, что это не сработало из коробки. Таким образом, примеры полных программ с простым синтаксисом также работают. Но мне действительно нравится-н..

Редактировать: re @chenyf

 raku -e ".say for $*ARGFILES" *.file
 

Та же ошибка. Похожие:

 raku -e ".say for $*ARGFILES.lines" *.file
 

Та же ошибка.

 raku -e "use IO::Glob; .say for glob('*.file')"
 

Сработало, как и ожидалось! Расширяющийся:

 raku -e "use IO::Glob; .say for glob('*.file').lines"
 

Нет такого метода «строки» для вызова типа «IO::Glob»

Приблизиться — возможно, расширение этого вопроса является достаточно хорошим обходным путем. Но возвращаясь к одной строке, я пытаюсь:

 raku -e "use IO::Glob; .say for glob($*ARGFILES)" test.file
 

Не удается разрешить глобус вызывающего абонента(IO::ArgFiles:D); ни одна из этих подписей не совпадает.

Хорошо — давайте вернемся к безопасности струн:

 raku -e "use IO::Glob; .say for glob($*ARGFILES.Str)" test.file
 

Yes! SO..:

 raku -e "use IO::Glob; .say for glob($*ARGFILES.Str).lines" test.file
 

No such method ‘lines’ for invocant of type ‘IO::Glob’

I clearly need to read more of the manual. But let’s retreat a little and see if my use case works:

 raku -e "use IO::Glob; .say for glob($*ARGFILES.Str)" *.file
 

Failed to open file C:..*.file: Invalid argument

The same error I started off with. Could this just be a raku on windows error?

Edit:

 raku -MIO::Glob -e "my @files = (map { glob($_).dir }, @*ARGS).flat; for @files -> $file { say $_ for $file.lines }" *file *file2 *5
 

У меня есть три набора файлов. Я почти могу смириться с этим решением — за исключением того, что по какой-то причине строки печатаются с «s

Есть какие-нибудь идеи по сокращению и избавлению от кавычек?

РЕДАКТИРОВАНИЕ Работы с автоматической глобализацией переменной $*ARGFILES:

 raku -MIO::Glob -n -e "BEGIN { @*ARGS = (map { glob($_) }, @*ARGS).flat }; .say" *.file *.file2
 

Это имеет то преимущество, что все еще выглядит как оригинальный лайнер; он использует-n! Ему просто нужно было выполнить глобализацию, которая кажется ошибкой при создании $*ARGFILES.

 raku -MIO::Glob -e "BEGIN { @*ARGS = (map { glob($_) }, @*ARGS).flat }; .say for $*ARGFILES.lines" *.file *.file2
 

Преобразование в $*ARGFILES.строки выше показывают, что $*ARGFILES динамически получает свои значения из @*ARGS.

Редактировать

наконец, оказывается, что функция glob не работает с каталогами, по крайней мере, в Windows (в документации есть пример, который просто не работает).

 #Example from https://github.com/zostay/raku-IO-Glob
for glob("src/core/*.pm") -> $file { say ~$file }

#mine that doesn't work
raku -MIO::Glob -e "for glob('..*.file') -> $file { say ~$file }"

#mine that does work.
raku -MIO::Glob -e "for glob('*.file').dir('..') -> $file { say ~$file }"

#And therefore the final modification of the script above:
raku -MIO::Glob -e "BEGIN { @*ARGS = (map { glob(.IO.basename).dir(.IO.dirname) }, @*ARGS).flat };  .say for $*ARGFILES.lines" ..*.file
 

Комментарии:

1. возможно $*ARGFILES , поможет, например: andrewshitov.com/2018/12/24/…

2. Отредактировал ответ, чтобы показать тестирование с помощью $*ARGFILES.

3. Кстати, спасибо ченифу за ссылку — я действительно проверил ее, и его примеры старательно избегали нескольких файлов, а тем более глобализации. Я действительно оставил вопрос в комментариях.

4. И raku -e '$*ARGFILES.lines.say;' *.txt то, и другое, и raku -e '.say for $*ARGFILES.lines;' *.txt работайте в моей старой системе macOS. Первая однострочная строка возвращает каждый *.txt файл в одной строке, а вторая однострочная строка дает линейный возврат, неотличимый от cat (каждый возвращает пять *.txt файлов из моего текущего каталога).

5. Может быть, ошибка разрешений окна (каталога)? Или неправильно указан путь к файлу? Код raku -ne ".say if /mydatabegin/;" *.txt здесь работает нормально (обратите внимание на начальную . точку).

Ответ №1:

Мое рудиментарное понимание глобализации файлов заключается в том, что оболочка обрабатывает это-и поскольку кажется, что вы находитесь в Windows, все ставки могут быть отменены. Единственным исключением может быть, если вы используете WSL Windows-подсистему для Linux, что должно дать вам больше возможностей, подобных Unix/Linux:

https://docs.microsoft.com/en-us/windows/wsl/about

Согласно документу Microsoft, приведенному ниже, Windows имеет две встроенные оболочки, CMD.exe и Powershell (я считаю, что оболочка WSL выше необязательна):

«Обзор командной оболочки»

«Windows имеет две командные оболочки: командную оболочку и PowerShell. Каждая оболочка представляет собой программное обеспечение, которое обеспечивает прямую связь между вами и операционной системой или приложением, обеспечивая среду для автоматизации ИТ-операций».

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands


Ниже показано, что работает в довольно старой bash/MacOS системе. С -ne флагом командной строки (без автоматической печати) :

 raku -ne 'print $_ ~ "n";'
raku -ne 'say $_ ;' 
raku -ne '.say;'
 

С -pe флагом командной строки (автопечатка) :

 raku -pe 'print "";'
raku -pe ''
 

Я буквально только что распечатал содержимое пяти (5) *.txt файлов, используя приведенные выше команды. -e Флаг всегда завершает кластер флагов командной строки, но может быть объединен (см. -M Флаг ниже для исключения).

Теперь, поскольку вы находитесь в Windows, вам, возможно, придется поменять "" двойные кавычки на '' одинарные (и наоборот!). Но, надеюсь, это поможет вам начать. [Любые дальнейшие проблемы, и вам, возможно, придется указать полный путь к вашему исполняемому Rakudo].

Если вы хотите, чтобы Raku обработал для вас перемещение по каталогу, есть dir() команда Raku, которую можно использовать в сочетании с ее :test наречием (параметром). Сравните ниже, когда в вышеупомянутом каталоге с пятью (5) *.txt текстовыми файлами (удалите .elems вызовы для печати фактического текста):

 raku -e '.lines.elems.say for dir(test => / .txt $ /);'
14
16
34
1
16
 

против:

 raku -e '.lines.elems.say for $*ARGFILES;' *.txt
81
 

https://docs.raku.org/routine/dir


ДОБАВЛЕНИЕ: Мой осмотр глоссария Raku P5-P6 предполагает, что разработчики намеренно исключили glob функцию Perl5 из Perl6/Raku, выбрав вместо этого более мощную встроенную dir() процедуру. Ссылки ниже:

https://docs.raku.org/language/5to6-perlfunc#index-entry-glob_-_perlfunc
https://docs.raku.org/routine/dir

Модуль Raku IO::Glob не является основным (и … я никогда его не пробовал). Но если вы работаете в командной строке и хотите загрузить модуль, вы используете (например) -MIO::Glob , за которым следует -e , -ne , или -pe и т. Д. (Кроме того, нет необходимости включать use IO::Glob; строку в ваш однострочный Raku, она уже загружена через -M ).

Смотрите однострочные примеры Raku с Txt::CSV модулем и/или XML модулем по ссылкам ниже:

https://unix.stackexchange.com/search?q=[csv] Раку
https://unix.stackexchange.com/search?q=[xml] Раку

Следуйте дополнительным окнам CMD.exe обсуждение/резолюция ниже:

https://github.com/rakudo/rakudo/issues/4550

Комментарии:

1. Довольно странный вид приведен raku -pe 'print "";' выше, потому что его можно легко изменить, чтобы добавить в ваши файлы номера строк: raku -pe 'print $,"t";' *.txt ИЛИ raku -pe 'print $~"t";' *.txt

2. Спасибо @jubilatious1 Во-первых, это должно быть в Windows, поэтому я все еще решаю проблему с Windows. Во-вторых, я не хочу изменять код после написания сценария / программы, поэтому я использую *.файлы.

3. Как твои «.строчки. скажем, конструкция @files » — однако она печатает скобки и кавычки. АРРР.

4. @GerardONeill Я отвечал на распространенные вопросы по обработке текста в Raku в Unix и Linux , просто выполните поиск «Raku» в поле вверху. Если иногда вы видите однострочный ответ Raku с дополнительными скобками и кавычками, удалите все звонки .raku и/или .perl . Я буду время от времени включать эти звонки, чтобы визуализировать n новые строки и т. Д.

5. К вашему сведению — .put не печатает родителей, в отличие от .скажем. Что-то о методе Str против метода gist.

Ответ №2:

Общий ответ — это не ошибка. Программы Windows должны иметь дело со своим собственным глобализацией, если они этого хотят. Для меня имеет смысл заставить его работать в исполняемом файле raku; это устраняет специфические для платформы сюрпризы и упрощает однострочные.

Но другие так не считали, и есть достаточно простое решение — создайте свой собственный модуль, чтобы код оставался последовательным и вызывался относительно просто.

Вот модуль для начала. Есть место, чтобы добавить такие вещи, как

  • переключатель для обязательного успешного совпадения
  • переключатель, указывающий, что сбойный глобус должен оставаться в переменной @*ARGS
  • после этого переключитесь только на глобус.
  • процедура для применения глобулирования вместо автоматического выполнения этого. Это позволит вам удалить переключатели, не относящиеся к файлам
  • соберите каждый шарик в свой собственный список (возможно, с помощью переключателя).

Модуль:

 unit module CLGlob:ver<1.0>:auth<pureabsolute>;

use IO::Glob;

@*ARGS = map { .Str }, (map { glob(.IO.basename).dir(.IO.dirname) }, @*ARGS ).flat;
 

Примечание: выражение во второй карте может быть упрощено, если функция glob работает для Windows с каталогами.

Примечание: Я преобразую каждый элемент в .Str, чтобы сделать @*ARGS согласованными. Файлы $*ARGFILES работали без этого, поэтому некоторая обработка может быть сохранена, если вы никогда больше не будете смотреть на @*ARGS.

Наконец, конечный результат:

 raku -MCLGlob -ne ".say" ..*.file ..*.file2
 

Ура.

Комментарии:

1. Вы отредактировали свою операцию, чтобы указать, что пример кода для IO::Glob модуля не работает. Вы открыли проблему на Github в соответствующем репо?

2. Нет, пока нет. Признаюсь, я и так потратил на это слишком много времени. Но в конце концов я это сделаю.