![Команда Powershell в пакетном файле: удалить все строки из текстового файла, кроме строк с «foo» и «bar»?](https://rvso.com/image/1654781/%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0%20Powershell%20%D0%B2%20%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BD%D0%BE%D0%BC%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B5%3A%20%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8%20%D0%B8%D0%B7%20%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%2C%20%D0%BA%D1%80%D0%BE%D0%BC%D0%B5%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%20%D1%81%20%C2%ABfoo%C2%BB%20%D0%B8%20%C2%ABbar%C2%BB%3F.png)
У меня есть текстовый файл с этими тремя строками:
This line contains foo.
This line contains bar.
This line has neither.
Я могу запустить следующую команду в файле «.bat» (рядом с указанным выше файлом «.txt»), и она удалит все строки в текстовом файле, кроме строк, содержащих «foo»:
Powershell.exe -Command "gci *.txt | foreach { (cat $_.FullName | ? { $_ -like '*foo*' }) | set-content $_.FullName}"
Запуск этой команды даёт ожидаемый эффект, оставляя в текстовом файле только эту строку:
This line contains foo.
Теперь проблема: что делать, если я хочу сохранить строки, содержащие «foo»и«bar» в строке?
До сих пор я перепробовал, наверное, 40 или 50 различных комбинаций: добавлял символ вертикальной черты: *foo*|*bar*
, убирал звездочки foo|bar
, добавлял звездочки только в начале и в конце: *foo|bar*
, использовал запятую, не использовал запятую, использовал точку с запятой, не использовал точку с запятой, дублировал -like
команду с символом и без него $_
и многими другими способами.
Ничего не работает — при каждой попытке до сих пор я получал один и тот же текстовый файл, в котором исходные три строки содержали foo (строка 1), bar (строка 2) и none (строка 3).
Чтобы убедиться, что я не редактирую команду и не совершаю ошибку, я периодически удаляю свои правки и снова запускаю команду, чтобы просто убрать строки без «foo», и это работает, или просто снова вставляю команду, снова проверяю ее, а затем начинаю пытаться редактировать ее, чтобы включить «bar», но безрезультатно.
Я уже задавал этот вопрос недавно, но, полагаю, моя формулировка заголовка была неясной. Кто-то пытался ответить на него, но каждый предоставленный ими ответ не сработал, по крайней мере, когда я помещаю команду в пакетный файл и запускаю ее рядом с текстовым файлом, возможно, это работает для них, используя другой метод, нежели тот, который использую я, я не знаю.
Обратите внимание, что я использую команду PowerShell в пакетном файле!Я не печатаю в консоли и не использую скрипты PS1. Мне не нужно ничего этого делать, потому что самая первая команда, которую я упомянул выше,работаетчтобы удалить все строки с "foo".
Очевидно, поскольку это работает, команду можно использовать в качестве основы для дополнения, чтобы она могла обрабатывать «foo» и «bar» в одной команде.
Если, конечно, это не на 100% невозможно — а вот после 4 дней попыток повторить 40 или 50 различных вариаций команды — я начинаю это подозревать!
Пожалуйста, если кто-нибудь ответит на это, опубликуйте команду пакетного файла, как у меня выше. Пожалуйста, не говорите мне переключиться на использование скриптов ps1 или давайте ответы, которые объясняют, что вводить в консольное окно.
Команду, которую я разместил выше, просто нужно немного изменить, чтобы можно было добавить «bar» к «foo», и тогда она будет обрабатывать более одной текстовой строки.
Причина, по которой это так сложно, кажется, в том, что если вы запускаете команду, чтобы удалить все строки, кроме тех, что содержат "foo", то вы уже удалили строки с "bar". Я подозреваю, что именно поэтому никто до сих пор не придумал работающего решения, а может быть, его просто нет.
Заранее спасибо всем, у кого есть работающий ответ. Обычно на такие вещи здесь отвечают очень быстро, или я просто продолжаю пробовать разные способы и у меня получается - но не в этот раз, это действительно сложно по какой-то причине.
решение1
Просто используйте два отдельных условия, соединенных оператором ИЛИ:
cat $_.FullName | ? { $_ -like '*foo*' -or $_ -like '*bar*' }
Скобки можно использовать для ясности, но они необязательны:
{ ($_ -like '*foo*') -or ($_ -like '*bar*') }
опубликуйте команду пакетного файла, как у меня выше. Пожалуйста, не говорите мне переключиться на использование скриптов ps1 или давайте ответы, которые объясняют, что вводить в консольное окно.
Это буквально одно и то же. Неважно, как вы вызываете скрипт PowerShell – сохраняете ли вы его в файле, передаете через командную строку или вводите с клавиатуры, это все равно скрипт PowerShell, и он следует тем же правилам синтаксиса.
решение2
Вместо этого вы можете использовать select-string
, который принимает регулярные выражения:
gci *.txt | % { (cat $_.FullName | select-string -pattern 'foo|bar') | set-content $_.FullName -Force }
select-string
позволяет вам в дальнейшем выполнять более сложное сопоставление регулярных выражений, если это необходимо.