Преобразование сценария Unix в сценарий Windows - эмуляция команды Sed в PowerShell - PullRequest
0 голосов
/ 23 июня 2018

У меня есть сценарий Unix (точнее, korn), который работает хорошо, и мне нужно преобразовать его в пакетный сценарий Windows.До сих пор я пытался вставить командную строку powershell в мой код, но это не работает.Пожалуйста, помогите, я только новичок в сценариях Unix и Windows, поэтому любая помощь подойдет.

Это строка кода, которую мне нужно преобразовать:

#create new file to parse ; exclude past instances of timestamp
    parsefile=/tmp/$$.parse
    sed -e "1,/$TIMESTAMP/d" -e "/$TIMESTAMP/d" $DSTLOGFILE > $parsefile

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

:set_parse_file
@powershell -Command "Get-Content $SCHLOGFILE | Foreach-Object {$_ -replace('1,/"$TIMESTAMP"/d' '/"$TIMESTAMP"/d'} | Set-Content $PARSEFILE"

Есть предложения, пожалуйста?

1 Ответ

0 голосов
/ 23 июня 2018

PowerShell имеет нет sed -подобных конструкций для обработки диапазонов строк (например, sed интерпретирует 1,/foo/ как ссылку на диапазон последовательных строк от строки 1 до следующей строки, которая соответствует регулярное выражение foo)

Эмуляция этой функции с построчной обработкой была бы намного более многословной , но сравнительно более краткая версия возможна, если входной файл обрабатывается в целом - это вариант только с файлами, достаточно маленькими, чтобы поместиться в память в целом (PSv5 + синтаксис).

Вот чистый код PowerShell:

$escapedTimeStamp = [regex]::Escape($TIMESTAMP)
(Get-Content -Raw $SCHLOGFILE) -replace ('(?ms)\A.*?\r?\n.*?' + $escapedTimeStamp + '.*?\r?\n') `
                               -replace ('(?m)^.*?' + $escapedTimeStamp + '.*\r?\n') |
  Set-Content -NoNewline $PARSEFILE

Обратите внимание, что [regex]::Escape() используется, чтобы убедиться, что значение $TIMESTAMP обрабатывается как литерал , даже если оно содержит метасимволы регулярных выражений (chars. С особым значением для механизма регулярных выражений). ).
Ваш ksh код этого не делает (и это нетривиально в ksh), поэтому, если - наоборот - $TIMESTAMP следует интерпретировать как как регулярное выражение, просто пропустите этот шаг и используйте $TIMESTAMP напрямую.

Оператор -replace основан на регулярных выражениях и использует механизм регулярных выражений .NET.

Для использования Get-Content -Raw требуется PSv3 +, а для Set-Content -NoNewline требуется PSv5 +. Вы можете заставить эту команду работать в более ранних версиях, но это требует больше усилий.

Вызов вышеприведенного из cmd.exe (командный файл) становится довольно громоздким - и вам всегда следует опасаться цитирования - но это должно работать:

@powershell.exe -noprofile -command "$escapedTimeStamp = [regex]::Escape('%TIMESTAMP%'); (Get-Content -Raw '%SCHLOGFILE%') -replace ('(?ms)\A.*?\r?\n.*?' + $escapedTimeStamp + '.*?\r?\n') -replace ('(?m)^.*?' + $escapedTimeStamp + '.*\r?\n') | Set-Content -NoNewline '%PARSEFILE%'"

Обратите внимание, как аргумент -command передается в виде одной строки "...", что в конечном итоге является наиболее безопасным и концептуально чистым способом передачи кода в PowerShell.
Также обратите внимание на необходимость встраивания пакетных переменных как %varname% в команду, и, поскольку они заключены во вложенный '...' выше, предполагается, что их значения не содержат ' символов.

Поэтому рассмотрите возможность реализации всего своего сценария в Powershell - в вашем распоряжении будет гораздо более мощный язык сценариев, и вы избежите головной боли при цитировании, которая исходит от соединяя два разнородных мира.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...