Это потому, что вам нужна оболочка, чтобы создать трубу или выполнить перенаправление. Обратите внимание, что cat
- это команда для конкатенации, не имеет смысла использовать ее только для одного файла.
cat file1.txt | xargs -I{} sh -c 'cat file2.txt | grep -e "$1"' sh {}
Не делать:
cat file1.txt | xargs -I{} sh -c 'cat file2.txt | grep -e {}'
так как это будет равносильно уязвимости инъекции команд. {}
будет расширен в аргументе кода для sh
и интерпретирован как код оболочки. Например, если бы в строке file1.txt
было $(reboot)
, это вызвало бы reboot
.
Ключ -e
(или вы также можете использовать --
) также важен. Без него у вас будут проблемы с regexps, начинающимися с --
.
Вы можете упростить вышеописанное, используя перенаправления вместо cat
:
< file1.txt xargs -I{} sh -c '< file2.txt grep -e "$1"' sh {}
Или просто передать имена файлов в качестве аргумента в grep
вместо использования перенаправлений, в этом случае вы можете даже отказаться от sh
:
< file1.txt xargs -I{} grep -e {} file2.txt
Вы также можете указать grep
искать все регексы сразу в одном вызове:
grep -f file1.txt file2.txt
Заметьте, однако, что в этом случае, это только один регексп для каждой строки file1. txt
, нет никакой специальной обработки кавычек, выполняемой xargs
.
xargs
по умолчанию рассматривает свой ввод как список пустых (в некоторых реализациях только пробел и табуляция, в других - любых символов из класса [:blank:]
текущей локали) или разделенных новой строкой слов, для которых можно использовать обратную косую черту, одинарные и двойные кавычки для экранирования разделителей (новая строка может быть экранирована только обратной косой чертой) или друг друга.
Например, при вводе типа:
'a "b'\" "bar baz" x\
y
xargs
без -I{}
команде будут переданы a "b"
, bar baz
и x
.
С -I{}
, xargs
получает одно слово в строке, но все же выполняет некоторую дополнительную обработку. Он игнорирует ведущие (но не последующие) пробелы. Пробелы больше не рассматриваются как разделители, но обработка кавычек все равно выполняется.
На приведенном выше xargs -I{}
передаст команде один a "b" foo bar x
аргумент. Также обратите внимание, что во многих системах, как того требует POSIX, это не будет работать, если длина слов превышает 255 символов. В общем, xargs -I{}
довольно бесполезен.
Если вы хотите, чтобы каждая строка передавалась дословно как аргумент команды, вы можете использовать расширение GNU xargs
-d '\n'
:
< file1.txt xargs -d '\n' -n 1 grep file2.txt -e
(здесь используется другое расширение GNU grep
, которое позволяет передавать опции после аргументов (при условии, что POSIXly correct не находится в окружении) или портативно:
sed "s/'/'\\\\\\''/g;s/.*/'&'/" file1.txt | xargs -n1 sh -c '
for line do
grep -e "$line" file2.txt
done' sh
Если вы хотите, чтобы каждое слово в file1. txt
(кавычки все еще распознаются), а не каждую строку (что также обойдет вашу проблему с пробелами в конце строки, если у вас все равно одно слово в строке), вы можете использовать xargs -n1
вместо -I
:
< file1.txt xargs -n1 sh -c '
for word do
grep -e "$word" file2.txt
done' sh
Чтобы удалить ведущие и последующие пробелы (но без обработки кавычек, которую делает xargs
), вы также можете сделать:
unset IFS # restore word splitting to its default
while read -r regexp; do
grep -e "$regexp" file2.txt
done < file1.txt
в итоге у меня сработало следующее:
удаление с помощью conda uninstall
и pip uninstall
удаление pip
не мог работать, пока я сначала удалю conda
ed, или, может быть, у меня это наоборот. закройте терминал и снова войдите в мою виртуальную среду conda ( источник активируйте my_env-name
)
pip install pygame
(НЕ conda install pygame
, что вызвало проблемы ) Извлеченный урок
У меня был установлен pygame с conda и pip, что, вероятно, было довольно плохой идеей для любого пакета. Предположительно, в будущем, когда что-то не будет работать после установки с помощью pip или conda, план Б должен быть сначала удалить с помощью pip или conda перед переустановкой с использованием другого. Наверное, это уже должно было быть известно...