Извините, если глупый вопрос, но я совсем новичок в ps..
Запуск Curl таким образом работает правильно (mailgun отправляет электронное письмо с вложением):
curl -s --user 'api:***' `
https://api.eu.mailgun.net/v3/***.com/messages `
-F from='Builder <[email protected]>' `
-F [email protected] `
-F subject='Build failed!!!' `
-F text='Your build has been failed.' -F attachment='1.txt'
Теперь пытаюсь добавить замену переменной:
$attstr = "-F attachment='1.txt'"
curl -s --user 'api:***' `
https://api.eu.mailgun.net/v3/***.com/messages `
-F from='Builder <[email protected]>' `
-F [email protected] `
-F subject='Build failed!!!' `
-F text='Your build has been failed.' $attstr
Похоже, переменная игнорируется (получение почты без вложения)





Команда, которую вы на самом деле выполняете:
curl -s --user api:*** `
https://api.eu.mailgun.net/v3/***.com/messages
... etc... `
-F text='Your build has been failed.' `
"-F attachment='1.txt'"
Обратите внимание на двойные кавычки вокруг -F attachment='1.txt' — я не знаю, как это интерпретируется в Curl, но он рассматривает содержимое переменной как строковые данные, а не как аргументы команды.
Если вы хотите, чтобы отдельные части вашей строковой переменной передавались как отдельные аргументы, попробуйте вместо этого разбить их как массив:
$cmdargs = @( "-F", "attachment='1.txt'" )
curl -s --user api:*** `
https://api.eu.mailgun.net/v3/***.com/messages
... etc... `
-F text='Your build has been failed.' `
@cmdargs
который выполнит:
curl -s --user api:*** `
https://api.eu.mailgun.net/v3/***.com/messages
... etc... `
-F text='Your build has been failed.' `
-F attachment='1.txt'
без окружающих кавычек.
Хороший способ диагностировать такого рода проблемы с анализом аргументов — использовать утилиту echoargs.exe с теми же аргументами, что и исходная команда (например, curl ...), и посмотреть, что она выводит на консоль...
PS> $attstr = "-F attachment='1.txt'"
PS> c:\src\so\echoargs.exe -s --user 'api:***' `
>> https://api.eu.mailgun.net/v3/***.com/messages `
>> -F from='Builder <[email protected]>' `
>> -F [email protected] `
>> -F subject='Build failed!!!' `
>> -F text='Your build has been failed.' `
>> $attstr
Arg 0 is <-s>
Arg 1 is <--user>
Arg 2 is <api:***>
Arg 3 is <https://api.eu.mailgun.net/v3/***.com/messages>
Arg 4 is <-F>
Arg 5 is <from=Builder <[email protected]>>
Arg 6 is <-F>
Arg 7 is <[email protected]>
Arg 8 is <-F>
Arg 9 is <subject=Build failed!!!>
Arg 10 is <-F>
Arg 11 is <text=Your build has been failed.>
Arg 12 is <-F attachment='1.txt'>
Command line:
"C:\src\so\echoargs.exe" -s --user api:*** https://api.eu.mailgun.net/v3/***.com/messages -F "from=Builder <[email protected]>" -F [email protected] -F "subject=Build failed!!!" -F "text=Your build has been failed." "-F attachment='1.txt'"
(прокрутите до конца строки, чтобы увидеть значение переменной в двойных кавычках).
Вы можете загрузить готовый двоичный файл echoargs.exe из разных мест (убедитесь, что вы доверяете тому, который используете), или исходный код доступен для самостоятельной компиляции (одну версию см. в этом GitHub gist https://gist.github.com). /pohatu/80b2b01492b0a22e874e).
В моем первоначальном ответе предлагалось использовать curl ... $cmdargs вместо разделения с помощью curl ... @cmdargs - @MathiasR.Jessen правильно указывает, что явное разделение переменной является предпочтительным подходом.
В дополнительном комментарии @mklement0 говорится:
сплаттинг на основе массива неявно применяется при вызове внешних программ
поэтому curl ... $cmdargs логически эквивалентен curl ... $cmdargs, когда $cmdargs представляет собой массив, но чтобы прояснить намерение, вероятно, лучше придерживаться curl ... @cmdargs.
Это очень простая, но эффективная утилита. Есть составленный на лету список, который я использовал несколько раз, чтобы убедиться, что я доверяю exe-файлу, которому звоню — см. gist.github.com/pohatu/80b2b01492b0a22e874e — никакой принадлежности, просто предпочитаю видеть чем я занимаюсь :-). (обратите внимание: кажется, что он компилируется только в Windows PowerShell, но exe-файл можно нормально вызвать из PowerShell (Core) 7.x)
А что, если мне нужно динамически создать строку args? Могу ли я добавлять аргументы один за другим в эту структуру данных? Например, у меня есть массив 1.txt, 2.txt, 3.txt, и я хочу перебрать его и построить @("-F", "attachment='1.txt'", "-F", " Attachment='2.txt'", "-F", "attachment='1.txt'") ?
Вы можете построить массив динамически: $cmdArgs = @(); if ( $something ) { $cmdArgs += @("-F" , "attachment='1.txt'") } (хотя обратите внимание на общепринятое мнение, что из соображений производительности следует избегать оператора «присваивания путем сложения» += для добавления к массивам).
работает как шарм. Большое спасибо @mclayton. Принятие
@mclayton Думаю, ты хочешь @cmdArgs здесь
@MathiasR.Jessen - возможно, но эмпирически echoargs ... $cmdArgs, похоже, здесь тоже работает (по крайней мере, дает тот же результат, что и echoargs ... @cmdargs в команде ^^^). Не уверен, что $cmdargs и @cmdargs могут работать одинаково для собственных команд с переменными строкового массива... (хотя для хеш-таблиц они определенно работают по-разному)
@MathiasR.Jessen - добавлено обновление для уточнения
@mclayton Извините, я не совсем ясно выразился в своем предыдущем сообщении: когда вы используете $cmdArgs для передачи массива аргументов, используйте @cmdArgs, чтобы PowerShell передавал их как отдельные строковые значения.
@MathiasR.Jessen - np. echoargs ... $cmdargs, похоже, передает значения в качестве отдельных аргументов для простого случая, когда $cmdargs представляет собой массив строк (echoargs ... $cmdargs дает Arg 12 is <-F> Arg 13 is <attachment='1.txt'> и -F attachment='1.txt' без кавычек в командной строке), но вы правы, что разметка, вероятно, более правильна. Я посмотрю на переработку ответа позже сегодня...
Модуль Pscx не обновлялся уже 6,5 лет. Все ли хорошо с PowerShell Core?
Другими словами: в сопоставлении «vs» команды идентичны, но только первый вывод выглядит правильно.
@MathiasR.Jessen - я переработал ответ, чтобы использовать явное разделение - на основе комментария @mklement0, curl ... $cmdaergs эквивалентно curl ... @cmdargs *для переменных со значением массива, но явное разделение делает намерение намного яснее - спасибо за предложения :-)...
@mklement0 - я отредактировал ответ - я в основном поспешил с разделом «обновление» и запутался - сравнение должно было выглядеть примерно так $cmdargs = @{ "aaa" = "bbb" }; echoargs $cmdargs -> "echoargs.exe" System.Collections.Hashtable, но сейчас я удалил весь этот раздел, так как он был лишним и отвлекал: -)...
Ух ты. Echoargs... Я пытался найти что-то подобное. Поиграюсь и обновлю