Сценарии: замена строк в файле очень специфическим способом. Как это сделать с powershell? - PullRequest
2 голосов
/ 15 марта 2020


Я новичок в регулярных выражениях и сценариях PowerShell.

В моем каталоге много javascript файлов. Большинство из них содержат выражение "window.open (...)" (возможно, сто раз).

Я хотел бы заменить все строки, содержащие одно из следующего:

  1. window.open('...', ...)
  2. window.open('...')
  3. window.open("...", ...)
  4. window.open("...")


Со следующим соответственно:

  1. window.open(encodeURI('...'), ...)
  2. window.open(encodeURI('...'))
  3. window.open(encodeURI("..."), ...)
  4. window.open(encodeURI("..."))

Короче говоря, я хотел бы вставить функцию encodeURI(...) впереди каждого первого аргумента в вызове функции window.open(...), если он существует (не нужно ничего делать с window.open(), который вообще не имеет аргументов).

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

Спасибо,
С уважением.

Ответы [ 3 ]

1 голос
/ 15 марта 2020

Вы можете искать и захватывать любые ' или ", которым предшествует window.open(, а затем захватывать все, что угодно, вплоть до следующего ' / ", на основе первой группы захвата:

<#
$lines = @'
window.open('...', ...)
window.open('...')
window.open("...", ...)
window.open("...")
'@ -split '\r?\n'
#> 

$lines -replace '(?<=window\.open\()([''"])(.*?\1)','encodeURI($1$2)'

('' - это не опечатка, это escape-последовательность строки из одинарных кавычек powershell )

Объяснение шаблона регулярного выражения:

(?<=               # open positive look-behind
  window\.open\(   # literal string `window.open(`
)                  # close positive look-behind
(                  # open capture group 1
  ['"]             # one of either ' or "
)                  # close capture group 1
(                  # open capture group 2
  .*?              # non-greedy match of 0 or more of any character
  \1               # back-reference to capture group one (ie. either ' or ")
)                  # close capture group 2
0 голосов
/ 18 марта 2020

Спасибо Матиасу за указание на то, что в этом случае я должен использовать парсер.

Я оставлю свой ответ как ссылку на любого, кто пытается найти аргументы функций в javascript. Я использовал библиотеки Esprima и Codegen для NodeJS для анализа моих JS файлов. Таким образом, я легко могу найти первые аргументы всех вызовов window.open(). В моем случае я заменяю первый аргумент, который является URL-адресом, на его кодированную версию, используя функцию encodeURI():

// This script finds all the calls "window.open" in a javascript file and converts
// the first argument of it to an encoded version of it.

function isWindowOpenCall(node) {
    if (node) {
    return (node && (node.type === 'CallExpression') &&
        (node.callee.type === 'MemberExpression') &&
        (node.callee.object.type === 'Identifier') &&
        (node.callee.object.name === 'window') &&
        (node.callee.property.type === 'Identifier') && 
        (node.callee.property.name === 'open'))
    }
    else return false;
}

// For JS Code Parsing
var esprima = require("esprima");

// For JS Code Regeneration
var escodegen = require("escodegen");

// For Reading File System
var fs = require("fs");

// For Reading the Lines
var readline = require('readline');

// Read File Name from Command Line
const fileNames = process.argv.splice(2);

// Read the file
var file = fileNames[0];
var sourceCode = fs.readFileSync(file, "utf-8");

// Parse the File
var parsedFile = esprima.parseScript(sourceCode, {}, function(node) {
    if (isWindowOpenCall(node)) {
        if(node){
        var arguments_parsed = node.arguments;
        var firstArgument_parsed = arguments_parsed[0];
        var firstArgument_plain = escodegen.generate(firstArgument_parsed);
        var firstArgumentModified_plain = "encodeURI(" + firstArgument_plain +")";
        var firstArgumentModified_parsed = esprima.parse(firstArgumentModified_plain);
        node.arguments[0] = firstArgumentModified_parsed;
        }
    }
});

// This is because the escodegen library automatically adds a ";" after changing
// the first argument, putting a syntax error in the script of the two forms:
// ");," in case `encodeURI` has multiple arguments or ";);" in case `encodeURI`
// has a single argument.
var result = escodegen.generate(parsedFile).replace(/;\),/g, '),');
var result = escodegen.generate(result).replace(/;\);/g, ');');
console.log(result);
0 голосов
/ 15 марта 2020

Это должен быть powershell? Если это было 10-30 файлов (скажем, довольно много, но не так много), я могу открыть их все в Notepad ++ или Visual Studio Code, найти и заменить (с помощью регулярных выражений) во всех открытых файлах и использовать:

(window\.open\()(.*?),?(.*?)\)

Заменить на:

$1encodeURI($3))

Демонстрация: https://regex101.com/r/TVxRyA/1

Пример использования редактора кода Visual Studio ...

Запуск файлов ...

enter image description here

Нажмите заменить все ...

enter image description here

Впоследствии ...

enter image description here

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