Использование awk в Python для вставки текста в файл - PullRequest
0 голосов
/ 07 марта 2020

У меня возникли проблемы с вставкой текста с использованием Python. У меня есть файл, Package.swift со следующим:

  targets: [
    .target(
      name: "LibCore",
      path: "lib/core/"
    ),
    .target(
      name: "LibAppData",
      dependencies: ["LibCore"],
      path: "lib/appdata/",
      swiftSettings: [.define("appdata")]
    ),

Я хочу вставить новый .target() прямо под отверстием targets: [

Это работает с использованием awk в zsh:

    awk '{print} /\.target\(/ && !n {print "      name: \"{full_name}\",\n      dependencies: \[\"LibCore\"\],\n      path: \"lib\/{short_name}\/\",\n      swiftSettings: [.define(\"{short_name}\")]\n    ),\n    .target("; n++}' Package.swift > Package-new.swift && mv Package-new.swift Package.swift

Я попробовал следующее в Python:

  1. subprocess.call([f"awk '{print} /\\.target\\(/ && !n {{print "      name: "{full_name}\",\n      dependencies: \\[\"LibCore\"\\],\n      path: \"lib\\/{short_name}\\/\",\n      swiftSettings: [.define(\"{short_name}\")]\n    ),\n    .target("; n++ "}}' Package.swift > Package-new.swift && mv Package-new.swift Package.swift"], shell=True) 
    
  2. subprocess.call(['awk.exe', '{print} /\\.target\\(/ && !n {print "      name: \"{full_name}\",\n      dependencies: \\[\"LibCore\"\\],\n      path: \"lib\\/{short_name}\\/\",\n      swiftSettings: [.define(\"{short_name}\")]\n    ),\n    .target("; n++}', 'Package.swift'])
    
  3.     tmp=tempfile.mkstemp()
        with open("Package.swift") as fd1, open(tmp[1],'w') as fd2:
            for line in fd1:
                line = line.replace("\\.target\\(",f"      name: \"{full_name}\",\n      dependencies: \\[\"LibCore\"\\],\n      path: \"lib\\/{short_name}\\/\",\n      swiftSettings: [.define(\"{short_name}\")]\n    ),\n    .target(")
                fd2.write(line)
        os.rename(tmp[1],"Package.swift")
    
  4.     newtext = '''\
                name: "{full_name}\",\n      dependencies: \\[\"LibCore\"\\],\n      path: \"lib\\/{short_name}\\/\",\n      swiftSettings: [.define(\"{short_name}\")]\n    ),\n    .target(
                '''
        filename = 'Package.swift'
        for line in fileinput.input([filename], inplace=True, backup='.bak'):
            if re.match(r'\\.target\\(', line):
                sys.stdout.write(newtext.format(l=line))
            else:
                sys.stdout.write(line)
    

Я также пробовал много вариантов этих попыток сбежать {}, но все равно каждый раз, когда я пытаюсь и получаю SyntaxError: invalid syntax запустить скрипт Если это не очевидно, Python не мой родной язык ?

Кто-нибудь знает, что мне не хватает?

Спасибо!

1 Ответ

0 голосов
/ 07 марта 2020

Проблемы:

  1. В 1 вы пропустили несколько символов двойной кавычки ", которые необходимо экранировать.
  2. Эта строка кажется синтаксически хорошей в Python, но запуск awk из Python всегда будет немного грубым. Однако это синтаксическая ошибка в awk . В отличие от некоторых других языков, строки в одинарных кавычках в Python по-прежнему обрабатывают escape-символы как escape-символы, поэтому, например, '"' и '\"' являются одним и тем же строковым литералом.

    Это означает, что этот пример: "name: \"{full_name}\"" преобразуется в "name: "{full_name}"", что портит ваше цитирование при подаче на awk.

  3. С этим вы ушли Слишком далеко в другую сторону: слишком много экранирования.

    Это: line = line.replace("\\.target\\(", никогда не совпадает, потому что ваш файл не содержит строку: \.target\(.

    Это не синтаксическая ошибка, однако, он просто ничего не сделает.

  4. Как говорится, теперь у вас две проблемы. Или, собственно, три проблемы. У вашего регулярного выражения та же проблема, что и в (3), match() - неправильный вызов для использования здесь, и string.format не работает таким образом.

    Неправильно экранированное регулярное выражение должно дать вам это ошибка, когда повторный пакет пытается использовать его:

    re.error: missing ), unterminated subpattern at position XX (где XX - номер строки)

    Если вы удалите лишний выход из регулярного выражения, вы получите это: \.target\( , Если у файла Package.swift нет отступа, с этим все будет в порядке, но он имеет отступ, и функция re.match получает совпадение только в том случае, если шаблон соответствует из начало строки , Вы хотите re.search, чтобы соответствовать где угодно. В качестве альтернативы вы можете изменить свой шаблон так, чтобы он соответствовал любому количеству пробельных символов перед строкой .target, например: [ \t]*\.target\(.

    Итак, последняя проблема: f-строки извлекают переменные из области видимости, которую они ' здесь, но string.format нет: каждое значение должно быть передано как значение словаря, а указанный здесь l=line ничего не делает? Кроме того, поскольку вы заменяете строку .target( вместо ее изменения или перезаписи, ваш выходной файл не является синтаксически допустимым Swift.

В некоторых случаях здесь я кажется, что вы пропустили важные части документации для библиотечных звонков, которые вы сделали? Если вы работаете над чем-то еще, официальная документация Python хорошая и очень полезная!

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

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