Shellwords
Shellwords
Shellwords 모듈은 UNIX Bourne 셸의 단어 파싱 규칙에 따라 문자열을 다루는 모듈이에요. 문자열을 셸에 친화적인 배열로 파싱하거나, 반대로 인자를 셸 명령줄에 안전하게 쓸 수 있는 문자열로 이스케이프해 줘요.
출처: Ruby 3.3 API
본문
shellwords() 함수는 원래 shellwords.pl을 포팅한 것에서 출발했고, IEEE Std 1003.1-2008, 2016 Edition의 Shell & Utilities 볼륨을 따르도록 수정됐어요.
사용법
Shellwords.split으로 문자열을 Bourne 셸 친화적인 배열로 파싱할 수 있어요.
require 'shellwords'
argv = Shellwords.split('three blind "mice"')
argv #=> ["three", "blind", "mice"]
Shellwords를 require 하면 String#shellsplit이라는 별칭도 쓸 수 있어요.
argv = "see how they run".shellsplit
argv #=> ["see", "how", "they", "run"]
큰따옴표는 특수 문자로 취급돼서, 맞지 않는(닫히지 않은) 따옴표는 ArgumentError를 발생시켜요.
argv = "they all ran after the farmer's wife".shellsplit
#=> ArgumentError: Unmatched quote: ...
반대로 Shellwords.escape(별칭 String#shellescape)는 셸 메타문자를 이스케이프해서 명령줄에 안전하게 쓸 수 있게 해 줘요.
filename = "special's.txt"
system("cat -- #{filename.shellescape}")
# runs "cat -- special\\'s.txt"
여기서 --를 붙인 이유를 짚어볼게요. 이것이 없으면 인자가 -로 시작할 때 cat(1)이 그걸 명령줄 옵션으로 취급해요. Shellwords.escape는 Bourne 셸이 원래 문자열로 다시 파싱할 수 있는 형태로 변환하는 걸 보장하지만, 임의의 인자를 명령에 넘겨도 해가 없게 하는 건 프로그래머의 책임이라는 점을 기억하세요.
Shellwords는 Array#shelljoin이라는 배열용 코어 확장도 함께 제공해요.
dir = "Funny GIFs"
argv = %W[ls -lta -- #{dir}]
system(argv.shelljoin + " | less")
# runs "ls -lta -- Funny\\ GIFs | less"
이렇게 해서 인자 배열로부터 완전한 명령줄을 만들 수 있어요.
Constants
VERSION
Public Class Methods
shellescape(str)
문자열을 Bourne 셸 명령줄에서 안전하게 쓸 수 있도록 이스케이프해요. str은 to_s에 응답하는 비문자열 객체일 수도 있어요.
이스케이프된 결과는 따옴표 없이(unquoted) 사용해야 하며, 큰따옴표나 작은따옴표 안에서 쓰기 위한 게 아니에요.
argv = Shellwords.escape("It's better to give than to receive")
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
String#shellescape는 이 함수의 축약형이에요.
argv = "It's better to give than to receive".shellescape
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
문자열이 사용될 셸 환경에 맞는 인코딩으로 인코딩하는 것은 호출자의 책임이에요. 멀티바이트 문자는 바이트가 아니라 멀티바이트 문자로 취급돼요. 길이가 0인 str은 빈 따옴표 문자열을 돌려줘요. escape는 이 메서드의 별칭이에요.
shelljoin(array)
인자 목록인 array로부터 명령줄 문자열을 만들어요. 모든 요소는 공백으로 구분해 하나의 문자열로 결합되는데, 각 요소는 Bourne 셸용으로 이스케이프되고 to_s로 문자열화돼요.
ary = ["There's", "a", "time", "and", "place", "for", "everything"]
argv = Shellwords.join(ary)
argv #=> "There\\'s a time and place for everything"
Array#shelljoin은 이 함수의 단축형이에요. Array#join에서 허용되는 것처럼 요소에 비문자열 객체를 섞을 수도 있어요.
output = `#{['ps', '-p', $$].shelljoin}`
join은 이 메서드의 별칭이에요.
shellsplit(line)
문자열을 UNIX Bourne 셸과 같은 방식으로 토큰 배열로 쪼개요.
argv = Shellwords.split('here are "two words"')
argv #=> ["here", "are", "two words"]
다만 이것이 명령줄 파서는 아니에요. 작은따옴표·큰따옴표·백슬래시를 제외한 셸 메타문자는 메타문자로 취급되지 않아요.
argv = Shellwords.split('ruby my_prog.rb | less')
argv #=> ["ruby", "my_prog.rb", "|", "less"]
String#shellsplit은 이 함수의 단축형이에요. shellwords와 split은 이 메서드의 별칭이에요.