2016-08-04 5 views
2

Как сделать что-то вроде diff <(echo aoeu) <(echo snth) в Scala?Как сделать замену процесса Bash в Scala?

Я попытался с помощью the sys.process interface следующим образом:

"diff <(echo aoeu) <(echo snth)".! 

... однако, это не интерпретирует <() как замещение подпроцесса.

+1

'' foo ".!' Использует '/ bin/sh', а не bash, в качестве интерпретатора оболочки' foo' в качестве скрипта. Даже если ваш '/ bin/sh' предоставлен bash, он запускается в режиме совместимости с POSIX при вызове таким образом. –

ответ

3
import scala.sys.process._ 

def diff(one: String, two: String): 
    String = Seq(
    "bash", "-c", """ 
     diff <(printf '%s\n' "$1") \ 
      <(printf '%s\n' "$2"); retval=$? 
     ((retval == 1)) || exit "$retval" 
    """, "_", one, two).!! 

Это может быть проверено на практике:

scala> diff("hello", "world") 
res1: String = 
"1c1 
< hello 
--- 
> world 
" 

Чтобы сломать рассуждения:

  • Вызов последовательности, а не строка, позволяет использовать данные (в моем примеры hello и world; в вашем, aoeu и), подлежащие передаче вне диапазона от кода. Это важно, чтобы избежать injection attacks, когда такое содержимое параметризуется.
  • Вызов bash в качестве исполняемого файла гарантирует, что синтаксис process substitution доступен.
  • Проверка состояния выхода 1 (и принудительное его на 0) позволяет избежать обработки scala в случае, когда diff возвращает статус выхода, указывающий, что два входа не идентичны как ошибка, гарантируя при этом, что другие ошибки все еще становятся исключениями в scala ,
  • Использование printf '%s\n' "$1" вместо echo "$1" позволяет избежать двусмысленностей в the POSIX definition of echo (см., В частности, раздел ИСПОЛЬЗОВАНИЕ ПРИМЕНЕНИЯ).
  • Передача явного аргумента _ заполняет слот argv[0], (aka $0).

Следует отметить, что применение последовательности, а не строка также предотвращает вас от необходимости оболочки на всех во многих случаях: Seq("hello", "world").! не нужно ссылаться на любую оболочку, но может быть реализована таким образом, чтобы непосредственно запускает исполняемый файл с именем hello, тогда как "hello world".! эквивалентен Seq("sh", "-c", "hello world").! с дополнительным исполняемым вызовом с как стоимостью исполнения, так и потенциальными уязвимостями безопасности, необходимыми для реализации. См. Shellshock для примера (в настоящее время почти повсеместно исправленного) случая, когда вызов оболочки, не имеющий явных контролируемых пользователем параметров, все еще может быть уязвимым на практике (при вызове с веб-сервера в соответствии с соглашениями CGI для экспорта параметров запроса в качестве среды переменных); избегая ненужных оболочек, является, таким образом, предпочтительным поведением, когда это возможно.

Смежные вопросы