Мне больше нравится u2ps , написанный Алексом Суйковым, который создает PDF-файлы гораздо меньшего размера с использованием системных шрифтов Unicode. Этой программы нет в Ubuntu или Fedora; вы должны скомпилировать его самостоятельно. Использование такое же:
$ u2ps text.txt | ps2pdf - text.pdf
(По сравнению с u2ps выход paps огромен ).
Рассмотрим данные в файле с именем file
. Требования для достижения результатов вашего примера немного отличаются от утверждений, которые вы опубликовали :
file
, соответствующие любому из этих критериев :1
и2
(это цифра, за которой следует пробел)foo
илиbar
Это может быть выражено в perl
путем сопоставления двух выражений и печати строки (в последовательности ), если они совпадают:
perl -ne '( !/^(1 |2 )/ or /foo|bar/ ) and print' file
Попутно все это требование можно выразить несколько иначе:
1
или2
foo
илиbar
И это очень удобно сопоставляется с awk
:
awk '!/^(1 |2 )/ || /foo/ || /bar/' file
В обоих случаях(perl
иawk
)RE ^(1 |2 )
можно упростить, выделив общий множитель и переписав его как^[12]
:
perl -ne '( !/^[12] / or /foo|bar/ ) and print' file
awk '!/^[12] / || /foo/ || /bar/' file
Использованиеsed
:
$ sed '/^[12]\>/ { /foo/ !{ /bar/ !d; }; }' file
1 foo
1 bar
2 contains bar and more
3 contains a random string
4 some other string
2 don't remove this line bar
14 keep this line
21 and also this line
7 bar
В приведенном выше примере sed
используется для проверки того, начинается ли каждая строка с 1
или 2
, за которой следует не -словесный символ (вы можете заменить \>
одним пробелом, если хотите ). Если это не так, то печатается строка. Если это так, строка проверяется на наличие подстроки foo
. Если эта подстрока существует, строка печатается. Если он не существует, аналогичная проверка выполняется для bar
, и строка печатается, если она совпадает, и удаляется, если нет.
Чтение логики из d
в обратном порядке :Строка удаляется, если она не соответствует bar
и не соответствует foo
, но начинается с 1
или 2
.
Использование Raku (, ранее известного как Perl _6)
raku -ne '.put if.grep( !/^ [ 1 | 2 ] \s / | / foo | bar / );'
ИЛИ
raku -ne '.put if.grep( { !/^ [ 1 | 2 ] \s /} | / foo | bar / );'
ИЛИ
raku -ne '.put if.grep( (none /^ [ 1 | 2 ] \s /) | / foo | bar / );'
Пример ввода:
1 foo
1 bar
1 someOtherString
2 contains bar and more
2 test
3 contains a random string
4 some other string
2 don't remove this line bar
2 but remove this line
14 keep this line
21 and also this line
7 bar
Пример вывода:
1 foo
1 bar
2 contains bar and more
3 contains a random string
4 some other string
2 don't remove this line bar
14 keep this line
21 and also this line
7 bar
Выше приведен грубый перевод кода @roaima на Perl5, хотя в Raku это собственно grep
операция. В Raku вы можете проверить отсутствие шаблона, используя показанный выше оператор отрицания !
(с/без окружающего кодового блока {...}
)или используя соединение none
(, связанное с Sets
в Раку ).
Вы могли заметить включение символа \s
в регулярное выражение. Это связано с тем, что необъявленные пробелы(\s
)и/или "... пробелы без кавычек в регулярном выражении обычно игнорируются..." по умолчанию в Raku, что делает код более читаемым. См. ссылки ниже.
https://docs.raku.org/language/regexes#Sigspace
https://raku.org
Мы можем с пользой использовать обходные пути для такого типа поиска по множеству -условий:
$ grep -vP '^(?=[12]\h)(?!.*(?:foo|bar))' file
Python можно использовать с модулем re для сопоставления и фильтрации на основе статуса результатов поиска.
python3 -c 'import re, sys
with open(sys.argv[1]) as f:
print(*filter(lambda x: re.match(r"(?![12]\s)",x) or re.search(r"foo|bar",x),f),sep="",end="")
' file