Ruby를 텍스트 처리용 cli 도구로 사용
왜 루비로 한 줄을 해요?
GUI보다 명령줄이 더 효율적인 용례에 익숙하다고 가정합니다.Unix as IDE이라는 제목의 이 시리즈도 참조하십시오.
bash
과 같은 셸 유틸리티는 내장된 명령과 스크립트 기능을 제공하여 각종 작업을 더욱 쉽게 해결하고 자동화할 수 있다.외부 *nix 명령, 예를 들어 grep
, sed
, awk
, sort
, find
, parallel
, ruby
등은 조합하여 사용할 수 있다.이러한 도구에 대한 익숙도에 따라 ruby -e 'puts readlines.uniq' *.txt
을 단독 대체품으로 사용할 수도 있고 특정한 용례에 맞추어 보충할 수도 있습니다.다음과 같은 일방통행 옵션이 있습니다.
ruby -e 'puts readlines.uniq {|s| s.split[1]}' *.txt
- 지정된 입력 파일 목록 ruby -rcommonregex -ne 'puts CommonRegex.get_links($_)' *.md
- 반복 행의 첫 번째 사본만 보관하고 두 번째 필드를 반복 기준으로 ruby
- 타사 CommonRegexRuby 라이브러리 stackoverflow: merge duplicate key values while preserving order - 최근 질문에
awk
보다 더 간단한 ruby
솔루션으로 대답하겠습니다.grep
, sed
, awk
등 도구에 비해 sed
의 주요 장점은 기능이 풍부한 정규 표현식 엔진, 표준 라이브러리와 제3자 라이브러리를 포함한다.awk
과 ruby
의 문법과 습관용법을 모르면 ruby
의 명령행 옵션을 배우는 것이 더 쉽습니다.주요 단점은 이 공구들에 비해 -0[octal]
의 속도가 느릴 수 있다는 것이다.명령줄 옵션
선택권
묘사
\0
레코드 구분자 지정(-a
, 매개 변수가 없는 경우)-n
자동 분할 모드(-p
또는 $_
($F
을 -c
으로 분할)-Cdirectory
구문만 확인-d
스크립트를 실행하기 전에 디렉터리에 cd를 복사하십시오$DEBUG
디버그 플래그 설정(-e 'command'
을true로 설정)-e
한 줄의 스크립트.-Eex[:in]
개 허용.생략 [프로그램 파일]-Fpattern
기본 외부 및 내부 문자 인코딩 지정split()
-a
자동 분할 모드(-i[extension]
)ARGV
현재 위치에서 -Idirectory
개의 파일을 편집합니다(확장자가 있을 경우 백업).$LOAD_PATH
-l
디렉토리 지정(여러 번 사용 가능)-n
행 끝 처리 사용'while gets(); ... end'
스크립트를 중심으로 -p
이 순환한다고 가정합니다.-n
순환이 sed
과 유사하다고 가정하지만 인쇄 줄도 -rlibrary
과 유사하다-s
스크립트를 실행하기 전에 라이브러리가 필요합니다.-S
스크립트 이름 다음에 스위치를 위한 스위치 해석을 사용합니다-v
PATH 환경 변수를 사용하여 스크립트 찾기-w
버전 번호를 인쇄한 다음 상세 모드를 엽니다-W[level=2|:category]
스크립트에 대한 경고 열기-x[directory]
경계 레벨 설정하기;0=침묵, 1=중등, 2=지루함--jit
# 이전에 텍스트 삭제!디렉터리에 cd가 있을지도 몰라요--jit-[option]
기본 옵션을 사용하여 JIT(실험적) 활성화-h
옵션을 사용하여 JIT(실험적) 활성화--help
이 메시지 표시, ruby
자세히 보기루비 코드 실행
ruby
프로그램 파일을 실행하려면 파일 이름을 매개 변수로 -e
명령에 전달하는 방법이 있습니다.$ echo 'puts "Hello Ruby"' > hello.rb
$ ruby hello.rb
Hello Ruby
짧은 프로그램에 대해서도 코드를 매개 변수로 ruby
옵션에 직접 전달할 수 있다.$ ruby -e 'puts "Hello Ruby"'
Hello Ruby
$ # multiple statements can be issued separated by ;
$ ruby -e 'x=25; y=12; puts x**y'
59604644775390625
$ # or use -e option multiple times
$ ruby -e 'x=25' -e 'y=12' -e 'puts x**y'
59604644775390625
거르다
grep
한 줄 프로그램은regexp와 일치하는 줄을 필터하는 데 사용할 수 있으며 sed
, awk
과 ruby
과 유사하다.많은 명령행 유틸리티와 유사하게 stdin
은 grep
과 파일 매개 변수의 입력을 받아들일 수 있다.$ # sample stdin data
$ printf 'gate\napple\nwhat\nkite\n'
gate
apple
what
kite
$ # print all lines containing 'at'
$ # same as: grep 'at' and sed -n '/at/p' and awk '/at/'
$ printf 'gate\napple\nwhat\nkite\n' | ruby -ne 'print if /at/'
gate
what
$ # print all lines NOT containing 'e'
$ # same as: grep -v 'e' and sed -n '/e/!p' and awk '!/e/'
$ printf 'gate\napple\nwhat\nkite\n' | ruby -ne 'print if !/e/'
what
기본적으로 sed
, awk
및 \n
은 입력한 내용을 자동으로 한 줄씩 순환한다(-n
을 줄 식별 문자로 한다).이 기능은 -p
또는 ruby
옵션에서 사용할 수 있습니다.앞에서 말한 바와 같이 -e
옵션은 코드를 명령행 매개 변수로 받아들인다.많은 단축키가 필요한 타자량을 줄일 수 있다.위의 예에서 정규 표현식 (한 쌍의 빗장 사이의 패턴 정의) 은 입력을 필터하는 데 사용된다.입력 문자열이 조건 상하문에 지정되지 않았을 때 (예:
if
) 전역 변수 $_
에 대한 테스트를 실행합니다. 이 변수는 입력 줄의 내용을 포함합니다. (정확한 용어는 input record입니다.)결론적으로 조건 컨텍스트에서 다음을 수행합니다./regexp/
은 $_ =~ /regexp/
의 바로 가기입니다.!/regexp/
은 $_ !~ /regexp/
의 바로 가기입니다.$_
도 print
방법의 기본 매개 변수이다. 이것이 바로 한 줄 프로그램에서 puts
방법보다 우수한 이유이다.이러한 기본값은 print
메서드에 대해 나중에 설명합니다.See ruby-doc: Pre-defined global variables for documentation on
$_
,$&
, etc.
다음은
stdin
이 아닌 파일 입력을 사용하는 예입니다.$ cat table.txt
brown bread mat hair 42
blue cake mug shirt -7
yellow banana window shoes 3.14
$ # same as: grep -oE '[0-9]+$' table.txt
$ ruby -ne 'puts $& if /\d+$/' table.txt
42
7
14
대치
sub
과 gsub
방법으로 수요를 검색하고 교체합니다.기본적으로 입력 문자열이 제공되지 않을 때, 이 방법은 $_
에서 실행됩니다.이러한 예제에서는 -p
옵션 대신 -n
옵션을 사용하여 각 입력 줄을 처리한 후 $_
값을 자동으로 인쇄합니다.$ # for each input line, change only first ':' to '-'
$ # same as: sed 's/:/-/' and awk '{sub(/:/, "-")} 1'
$ printf '1:2:3:4\na:b:c:d\n' | ruby -pe 'sub(/:/, "-")'
1-2:3:4
a-b:c:d
$ # for each input line, change all ':' to '-'
$ # same as: sed 's/:/-/g' and awk '{gsub(/:/, "-")} 1'
$ printf '1:2:3:4\na:b:c:d\n' | ruby -pe 'gsub(/:/, "-")'
1-2-3-4
a-b-c-d
$_
방법을 사용하지 않은 상태에서 !
을 어떻게 수정하는지 알고 싶을 수도 있습니다.왜냐하면 이러한 방법은 내부 핵의 일부이기 때문이다(자세한 정보는 ruby-doc: Kernel 참조). -n
또는 -p
옵션을 사용할 때만 사용할 수 있다.sub(/regexp/, repl)
은 $_.sub(/regexp/, repl)
의 바로 가기이며, 교체에 성공하면 $_
이 업데이트됩니다.gsub(/regexp/, repl)
은 $_.gsub(/regexp/, repl)
의 바로 가기이며, 교체에 성공하면 $_
이 업데이트됩니다.현장 처리
아래에 표시된 예시 입력 파일을 고려하십시오. 그 중 필드는 공백 문자로 구분됩니다.
$ cat table.txt
brown bread mat hair 42
blue cake mug shirt -7
yellow banana window shoes 3.14
다음은 전체 행이 아닌 특정 필드에 기반한 예들입니다.-a
옵션을 사용하면 입력 줄이 공백을 기반으로 분할되고 $F
글로벌 변수를 사용하여 필드 내용에 접근할 수 있습니다.선행 및 후행 공백이 억제되어 빈 필드가 생성되지 않습니다.$ # print the second field of each input line
$ # same as: awk '{print $2}' table.txt
$ ruby -ane 'puts $F[1]' table.txt
bread
cake
banana
$ # print lines only if last field is a negative number
$ # same as: awk '$NF<0' table.txt
$ ruby -ane 'print if $F[-1].to_f < 0' table.txt
blue cake mug shirt -7
$ # change 'b' to 'B' only for the first field
$ # same as: awk '{gsub(/b/, "B", $1)} 1' table.txt
$ ruby -ane '$F[0].gsub!(/b/, "B"); puts $F * " "' table.txt
Brown bread mat hair 42
Blue cake mug shirt -7
yellow banana window shoes 3.14
시작과 끝
입력을 읽기 전에 어떤 작업을 수행해야 할 때는
BEGIN{}
블록을 사용하고, 모든 입력을 처리한 후에는 END{}
블록을 사용하여 어떤 작업을 수행할 수 있다.$ # same as: awk 'BEGIN{print "---"} 1; END{print "%%%"}'
$ # note the use of ; after BEGIN block
$ seq 4 | ruby -pe 'BEGIN{puts "---"}; END{puts "%%%"}'
---
1
2
3
4
%%%
환경 해시
자동화와 스크립트 작성은 일반적으로 사용자의 입력, 파일, 셸 명령 출력 등을 받아들일 수 있는 명령을 구성해야 한다. 앞에서 말한 바와 같이 이 책은
bash
을 셸로 사용한다고 가정한다.셸의 환경 변수에 접근하려면 환경 변수의 이름을 문자열 키로 사용하여 특수한 해시 변수 ENV
을 호출할 수 있습니다.$ # existing environment variable
$ # output shown here is for my machine, would differ for you
$ ruby -e 'puts ENV["HOME"]'
/home/learnbyexample
$ ruby -e 'puts ENV["SHELL"]'
/bin/bash
$ # defined along with ruby command
$ # note that the variable is placed before the shell command
$ word='hello' ruby -e 'puts ENV["word"]'
hello
$ # the input characters are preserved as is
$ ip='hi\nbye' ruby -e 'puts ENV["ip"]'
hi\nbye
다음은regexp가 환경 변수 콘텐츠로 전달될 때의 또 다른 예입니다.$ cat word_anchors.txt
sub par
spar
apparent effort
two spare computers
cart part tart mart
$ # assume 'r' is a shell variable that has to be passed to the ruby command
$ r='\Bpar\B'
$ rgx="$r" ruby -ne 'print if /#{ENV["rgx"]}/' word_anchors.txt
apparent effort
two spare computers
As an example, see my repo ch: command help for a practical shell script, where commands are constructed dynamically.
외부 명령 실행
system
내부 핵 방법으로 외부 명령을 호출할 수 있다.문서를 보려면 ruby-doc: system을 참조하십시오.$ ruby -e 'system("echo Hello World")'
Hello World
$ ruby -e 'system("wc -w <word_anchors.txt")'
12
$ ruby -e 'system("seq -s, 10 > out.txt")'
$ cat out.txt
1,2,3,4,5,6,7,8,9,10
반환값 system
또는 전역 변수 $?
은 명령의 종료 상태를 조작하는 데 사용할 수 있습니다.$ ruby -e 'es=system("ls word_anchors.txt"); puts es'
word_anchors.txt
true
$ ruby -e 'system("ls word_anchors.txt"); puts $?'
word_anchors.txt
pid 6087 exit 0
$ ruby -e 'system("ls xyz.txt"); puts $?'
ls: cannot access 'xyz.txt': No such file or directory
pid 6164 exit 2
외부 명령의 결과를 저장하려면 백틱스 또는 %x
을 사용합니다.$ ruby -e 'words = `wc -w <word_anchors.txt`; puts words'
12
$ ruby -e 'nums = %x/seq 3/; print nums'
1
2
3
See also stackoverflow: difference between exec, system and %x() or backticks
요약
본고는
ruby
cli가 사용하는 흔한 옵션과 전형적인 cli 텍스트 처리 예시를 소개한다.grep
, sed
, awk
등 특정 용도의 cli 도구는 보통 속도가 빠르지만 ruby
은 더욱 광범위한 표준 라이브러리와 생태계를 가지고 있다.만약 당신이 ruby
에 익숙하지만, 이러한 cli 도구에 익숙하지 않다면, 너무 많은 것을 배울 필요가 없습니다.Ruby one liners 레시피
만약 당신이 이 글을 좋아하고 더 많은 정보를 알고 싶다면, 아래의 링크를 사용하여 나의 전자책을 보십시오.이번 주 일요일(2020년 10월 4일)까지 무료로 내려받을 수 있다.
Reference
이 문제에 관하여(Ruby를 텍스트 처리용 cli 도구로 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/learnbyexample/using-ruby-as-a-cli-tool-for-text-processing-9jn텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)