Что касается вопроса № 2 ( Как я могу исправить эту программу [...]? ):
Полезный ответ Кирилла Пашкова предлагает элегантное решение на основев операторе switch
.
Обратите внимание, однако, что его решение:
основано на Sub <name>
/ Function <name>
частях оператора , не являющихсяна той же строке , что и соответствующие End Sub
/ End Function
детали - хотя это обычно случай, это не синтаксическое требование;например, Sub Foo() WScript.Echo("hi") End Sub
- в одной строке - тоже работает.
в соответствии с вашей собственной попыткой решения, слепо добавляет ()
к Sub
/ Function
определениям, которыене будет работать с процедурами ввода / функциями, которые уже имеют объявления параметров (например, Sub Foo (bar, baz)
).
Следующее решение:
- также работает с однострочный
Sub
/ Function
определение - правильно сохраняет объявления параметров
Get-Content $vbs | ForEach-Object {
$_ -replace '\b(?:sub|function)\s+(\w+)\s*(\(.*?\))', 'function $1$2 {' `
-replace '\bend\s+(?:sub|function)\b', '}'
} | Out-File $js
Вышеприведенное опирается на регулярных выражений (обычныйвыражения) для преобразования ввода;подробности о том, как результаты сопоставления регулярных выражений можно ссылать в операнде строки замены оператора -replace
, см. этот ответ .
Предупреждение : существует множество другихсинтаксические различия между VBScript и JScript, которые не охватываются вашим подходом, в частности то, что VBScript не имеет оператора return
и вместо этого использует <funcName> = ...
для возврата значений из функций.
Что касается вопроса № 1:
Однако, когда я открываю outfile.js, я вижу только одну строку:
False
[...]
1. Почему это происходит?
Все, кроме вызова first ForEach-Object
командлета, выполняются в отдельных операторах , потому чтоначальный конвейер заканчивается с первым вызовом Out-File $js
.
последующими ForEach-Object
вызовами каждого началановый конвейер , и так как каждый конвейер заканчивается Out-File $js
, каждый , такой конвейер записывает в файл $js
- и тем самым перезаписываетes независимо от того, что написал предыдущий.
Следовательно, последний конвейер определяет конечное содержимое файла $js
.
AForEach-Object
что запускает конвейер получает нет ввода .Однако связанный с ним блок скрипта ({...}
) все еще вводится один раз в этом случае, с $_
, равным $null
[1] :
Последний конвейер начинается с Foreach-Object { $_ -match "End Function" }
, поэтому его вывод эквивалентен $null -match "End Function"
, что дает $False
, потому что -match
с скаляром LHS (один входной объект) выводит логическое значение, которое указывает, было ли найдено совпадение.
Следовательно, учитывая, что средний сегмент конвейера (Foreach-Object { $_ -replace "End Function", "}" }
) действует no-op ($False
переводится в 'False'
, и поэтому оператор -replace
не находит соответствия для замены и пропускает строковый ввод без изменений), Out-File $js
получаетстрока 'False'
и записывает именно это в выходной файл $js
.
Даже если вы преобразовали свои отдельные команды в single конвейер с одним Out-File $js
сегментом в самом конце, ваша команда не будет работать, однако:
Учитывая, что Get-Content
отправляет строки входного файла по конвейеру одна за другой , что-то вроде $_ -match "Sub "
снова выдаст Boolean результат - указывающий, соответствует ли соответствующая строка ($_
)строка "Sub "
- и передать , что включено.
Хотя вы можете превратить -match
в фильтр , сделав LHS массивом - заключив его в оператор подвыражения массива @(...)
;например, @($_) -match "Sub "
- это будет:
- проходить строку, содержащую подстроку
Sub
- в целом , и - пропустить строки, которые не.
Другими словами: это не будет работать так, как задумано, потому что:
- строк, которые не содержат совпадающую подстроку, будут опущены из выходных данных и
- совпадающие строки отражаются полностью в
$_
в следующем сегменте конвейера, а не только в согласованной части .
[1] Строго говоря, $_
сохранит любое значение, которое оно имело в текущей области, но это будет не $null
, если вы явно присвоили значение $_
- учитывая, что $_
- это автоматическая переменная, которая обычно контролируется самой PowerShell, однако делать это не рекомендуется - см. это обсуждение GitHub .