2016-10-17 2 views
2

Допустим, у меня есть тестовый файл с именем testfile.txt, содержащий строку ниже:Найти и заменить строку, содержащую обе двойные кавычки и скобки

one (two) "three" 

Я хочу использовать PowerShell, чтобы сказать, что если вся строка существует поместите линию непосредственно под ним со значением:.

four (five) "six" 

(Обратите внимание, что он включает в себя как пробелы, скобки и двойные кавычки Это очень важно, так как проблема, которую я имею, я думаю, вытекания скобки и двойной кавычки).

Так что результат будет:

one (two) "three" 
four (five) "six" 

Я думал, что самый простой способ сделать это было бы сказать, что если первая строка найдена, замените его самую первую строку снова, и в новая строка, образующая новую строку, включенную в ту же команду. Мне было трудно помещать строки в строку, поэтому я попытался использовать переменную herestring, в которой читается весь текстовый блок с форматированием. Он по-прежнему не разбирает полную строку с кавычками в конвейере. Я новичок в PowerShell, поэтому не сдерживайтесь, если увидите что-то глупое.

$herestring1 = @" 
one (two) "three" 
"@ 

$herestring2 = @" 
one (two) "three" 
four (five) "six" 
"@ 

if((Get-Content testfile.txt) | select-string $herestring1) { 
"Match found - replacing string" 
(Get-Content testfile.txt) | ForEach-Object { $_ -replace $herestring1,$herestring2 } | Set-Content ./testfile.txt 
"Replaced string successfully" 
} 
else { 
"No match found"} 

Вышеуказанное только что дает «Ничего не найдено» каждый раз. Это связано с тем, что он не находит первую строку в файле. Я попробовал варианты с использованием backtick [`] и удвоения кавычек, чтобы попытаться сбежать, но я подумал, что точка в строке здесь состоит в том, что она должна анализировать текстовый блок, включая все форматирование, поэтому мне не нужно.

Если изменить файл содержит только:

one two three 

, а затем изменить herestring соответственно:

$herestring1 = @" 
one two three 
"@ 

$herestring2 = @" 
one two three 
four five six 
"@ 

Тогда он работает нормально, и я получаю строку заменить, как я хочу.

ответ

0

Просто используйте Select-String Командлет с переключателем -SimpleMatch:

# .... 
if((Get-Content testfile.txt) | select-string -SimpleMatch $herestring1) { 
# .... 

-SimpleMatch

Указывает, что командлет использует простой матч, а не обычный матч выражения. В простом совпадении Select-String выполняет поиск ввода для текста в параметре Pattern. Он не интерпретирует значение параметра параметра Pattern как выражение регулярного выражения.

Source.

+0

Большое спасибо за быстрый отклик. – coursemyhorse

1

Как Мартин отмечает, вы можете использовать -SimpleMatch с Select-String, чтобы избежать разбора это как регулярное выражение.

Но -replace все еще будет использовать регулярное выражение.

Вы можете избежать шаблон для регулярных выражений с помощью [RegEx]::Escape():

$herestring1 = @" 
one (two) "three" 
"@ 

$herestring2 = @" 
one (two) "three" 
four (five) "six" 
"@ 

$pattern1 = [RegEx]::Escape($herestring1) 

if((Get-Content testfile.txt) | select-string $pattern1) { 
"Match found - replacing string" 
(Get-Content testfile.txt) | ForEach-Object { $_ -replace $pattern1,$herestring2 } | Set-Content ./testfile.txt 
"Replaced string successfully" 
} 
else { 
"No match found"} 

Регулярные выражения интерпретируют скобки () (то, что вы вызываете скобки) в качестве специальных. По умолчанию пробелы не являются специальными, но могут быть с определенными параметрами регулярного выражения. Двойные кавычки не представляют проблемы.

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

[RegEx]::Escape() обеспечит ничего особенного, чтобы регулярное выражение экранируются, так что шаблон регулярного выражения будет интерпретировать его как буквальным, так что ваша картина будет в конечном итоге выглядит так: one\ \(two\)\ "three"

+0

Фантастический, благодаря вам и то, и другое. Могу я просто спросить, хотя в приведенном выше примере я хочу понять, почему нам не нужно использовать метод escape-выражения для $ herestring2? Итак, я имею в виду, что я должен был бы также ввести переменную $ pattern2, делая то же самое. Кажется, что это не было необходимо, поэтому я не понимаю, как он использует $ herestring2 в порядке. Большое спасибо. Первое сообщение на этом сайте и ответило в значительной степени мгновенно, спасая меня так много времени. Очень благодарен. – coursemyhorse

+0

@coursemyhorse Значение замены не является шаблоном регулярного выражения. Он может использовать несколько специальных символов (например, «$ 1», например, для ссылки на обратные ссылки групп захвата), но если нет групп захвата, это будет интерпретировать буквально в любом случае. Таким образом, экранирование '$ herestring2' приведет к замене строки, содержащей лишние символы, которые вам не нужны. – briantist

+0

Вы правы, если я добавлю его, как я предложил, он дает результат как: – coursemyhorse

Смежные вопросы