Я пытаюсь написать команду узла, которая просто оценивает и выводит код, переданный в аргументах. В идеале мне не нужно было бы заключать их в кавычки или сначала помещать в файл. Если сценарий node / bash называется n и находится в пути, я хочу, чтобы это произошло:
$ n 1 + "1"
11
Я попытался добиться этого, просто объединив все аргументы оболочки с пробелом, но в приведенном выше случае не удалось, потому что аргументы - это ["1", "+", "1"], поскольку двойные кавычки являются частью синтаксиса оболочки для определения аргумента. Это означает, что вместо этого я получаю следующее:
$ n 1 + "1"
2
Вот мои попытки в обоих узлах
#!/usr/bin/node
console.info(eval(process.argv.slice(2).join(' ')))
и бить
#!/bin/bash
node -e "console.info(eval(\"$*\"))"
Позже я попытался подойти к этому с другой стороны: я знал, что ps <pid> хранит полную команду, и думал, что он никак не проанализирует ее. Вот почему я подумал, что это невозможно сделать без добавления каких-то странных внутренних ловушек. Поэтому я написал сценарий узла для вывода команды ps-stored с текущим pid:
#!/usr/bin/node
require('child_process').exec(`ps ${process.pid}`, (err, stdout) => {
const [ headers, process ] = stdout.split('\n');
const commandIndex = headers.indexOf('COMMAND');
const command = process.substring(commandIndex).split(' ').slice(2).join(' ');
console.info(command);
})
к сожалению, ps также хранит проанализированный ввод:
$ n 1 + "1"
1 + 1
Я бы подумал, что в bash будет переменная окружения с неанализируемой текущей командой, но я не смог ее найти.
На самом деле я использую рыбы для фактического запуска команды, что может дать некоторое преимущество, но я понимаю, что вопрос о рыбе может быть не полезен такому количеству людей.
Может быть, есть способ получить эти аргументы из узла? Скрытая переменная окружения, которую я мог пропустить? Как я могу создать $ n 1 + "1", который различает аргументы в кавычках и без кавычек, чтобы выводить 11?
Перенос или экранирование не являются приемлемым решением!
@chepnerЯ задал вопрос именно потому, что хотел этого избежать
Почему? Гораздо проще сказать «Мой сценарий принимает выражение в следующем формате: ...», а затем передать его как одну строку в кавычках, чем заставлять ваш сценарий зависеть от конкретной семантики той оболочки, которая используется для вызова вашего сценария.





How would I go about creating an $ n 1 + "1" that distinguishes between quoted and unquoted arguments so that it outputs 11?
Вы этого не сделаете. Одна из фундаментальных идей сценария оболочки, которая применяется как к fish, так и к bash, заключается в том, что оболочка обрабатывает ваши аргументы, чтобы затем передать их программе.
Это относится не только к кавычкам (они используются для того, чтобы, например, "file with spaces" передавался как один аргумент, или чтобы '$var' не выполнял расширение переменных), но также и к * (который выполняет подстановку) и $ (который выполняет множество расширений, в зависимости от оболочки).
И если вы специально не хотите зависеть от конкретной оболочки, запускающей вашу программу (что вы, вероятно, не делаете), нет способа отключить это.
Одним из возможных решений может быть использование вашего инструмента в качестве REPL, чтобы пользователи вызывали n, а затем вводили выражение.
Другой - ожидать, что все выражение будет одним аргументом, чтобы пользователи могли использовать
n '1 + "1"'
который вы получите как 1 + "1".
Я также считаю, что вы немного переоцениваете проблему. Если вы используете оболочку, вам обычно нужно выполнять такого рода экранирование, и если бы в вашем инструменте его внезапно не было, это действительно сбивало бы с толку более, не меньше.
1и"1"производят одни и те же слова; оболочка удаляет кавычки перед передачей аргументов вn. Вероятно, вам лучше начать с аргумента в кавычках Один, представляющего все выражение, вместо того, чтобыnсоставлял выражение из нескольких аргументов.