루비 STDIN의 모범 사례?


307

Ruby의 명령 행 입력을 처리하고 싶습니다.

> cat input.txt | myprog.rb
> myprog.rb < input.txt
> myprog.rb arg1 arg2 arg3 ...

가장 좋은 방법은 무엇입니까? 특히 나는 빈 STDIN을 다루고 싶어하며 우아한 해결책을 원합니다.

#!/usr/bin/env ruby

STDIN.read.split("\n").each do |a|
   puts a
end

ARGV.each do |b|
    puts b
end

5
사소한 참고 사항 : 처음 두 명령 줄은 다음과 같은 관점에서 동일 myprog.rb합니다. input.txt파일이 stdin에 첨부됩니다 . 쉘이이를 관리합니다.
Mei

6
^^ 이것은 종종 "고양이의 쓸모없는 사용"으로 불립니다.
Steve Kehlet

18
@SteveKehlet 그러나 나는 그것이 더 현명하게 "고양이 학대"라고 믿습니다
OneChillDude

답변:


403

다음은 모호한 Ruby 모음에서 찾은 것들입니다.

따라서 루비에서 유닉스 명령의 간단한 노벨 구현은 다음과 cat같습니다.

#!/usr/bin/env ruby
puts ARGF.read

ARGF입력 할 때 친구입니다. 이름이 지정된 파일 또는 STDIN에서 모든 입력을 가져 오는 가상 파일입니다.

ARGF.each_with_index do |line, idx|
    print ARGF.filename, ":", idx, ";", line
end

# print all the lines in every file passed via command line that contains login
ARGF.each do |line|
    puts line if line =~ /login/
end

루비에서 다이아몬드 연산자를 얻지 못했지만 ARGF대체품으로 사용했습니다. 모호하지만 실제로는 유용한 것으로 판명되었습니다. -i명령 줄에 언급 된 모든 파일에 저작권 헤더를 다른 Perlism 덕분에 추가하는이 프로그램을 고려하십시오 .

#!/usr/bin/env ruby -i

Header = DATA.read

ARGF.each_line do |e|
  puts Header if ARGF.pos - e.length == 0
  puts e
end

__END__
#--
# Copyright (C) 2007 Fancypants, Inc.
#++

크레딧 :


12
ARGF는 갈 길입니다. Ruby는 파일과 stdin을 처리 할 수있는 방식으로 만들어졌습니다.
Pistos

1
(이것을보고 당신을 생각했습니다) 그 크레딧을 다시 만드십시오
deau

아주 좋습니다. AWK 작동 방식을 시뮬레이션 할 수있는 멋진 패턴이 있으면 하루가 끝날 것입니다 (제로 또는 최소한의 인터로 컷). :-)
것이다

아마도 그주의해야 idx모든 입력을 연결 가상 파일에서 "행 번호"가 아니라 각 개별 파일의 행 번호 될 것입니다.
Alec Jacobson

이주의 #!/usr/bin/env ruby -i리눅스에서 작동하지 않습니다 라인 : stackoverflow.com/q/4303128/735926
bfontaine

43

루비는 STDIN을 처리하는 다른 방법 인 -n 플래그를 제공합니다. 전체 프로그램을 STDIN의 루프 내부에있는 것으로 간주합니다 (명령 줄 인수로 전달 된 파일 포함). 예를 들어 다음 1 줄 스크립트를 참조하십시오.

#!/usr/bin/env ruby -n

#example.rb

puts "hello: #{$_}" #prepend 'hello:' to each line from STDIN

#these will all work:
# ./example.rb < input.txt
# cat input.txt | ./example.rb
# ./example.rb input.txt

8
#!/usr/bin/env ruby -n"ruby -n"이 유일한 인수로 / usr / bin / env에 전달되므로 세 부분으로 된 shebang 은 작동하지 않습니다. 자세한 내용은이 답변 을 참조하십시오. 명시 적으로 실행하면 스크립트 작동합니다 ruby -n script.rb.
artm September

5
@jdizzle : OSX에서는 작동하지만 Linux에서는 작동하지 않습니다. 정확히 문제입니다. 이식성 이 없습니다 .
mklement0

32

필요한 것이 확실하지 않지만 다음과 같은 것을 사용합니다.

#!/usr/bin/env ruby

until ARGV.empty? do
  puts "From arguments: #{ARGV.shift}"
end

while a = gets
  puts "From stdin: #{a}"
end

ARGV 배열은 first 이전에 비어 있기 때문에 getsRuby는 인수를 읽을 텍스트 파일 (Perl에서 상속 된 동작)로 해석하지 않습니다.

stdin이 비어 있거나 인수가 없으면 아무것도 인쇄되지 않습니다.

몇 가지 테스트 사례 :

$ cat input.txt | ./myprog.rb
From stdin: line 1
From stdin: line 2

$ ./myprog.rb arg1 arg2 arg3
From arguments: arg1
From arguments: arg2
From arguments: arg3
hi!
From stdin: hi!

18

아마도 이런 것?

#/usr/bin/env ruby

if $stdin.tty?
  ARGV.each do |file|
    puts "do something with this file: #{file}"
  end
else
  $stdin.each_line do |line|
    puts "do something with this line: #{line}"
  end
end

예:

> cat input.txt | ./myprog.rb
do something with this line: this
do something with this line: is
do something with this line: a
do something with this line: test
> ./myprog.rb < input.txt 
do something with this line: this
do something with this line: is
do something with this line: a
do something with this line: test
> ./myprog.rb arg1 arg2 arg3
do something with this file: arg1
do something with this file: arg2
do something with this file: arg3

stdin은 텍스트 일 ​​필요는 없습니다. 텍스트가 아닌 Notorius는 예를 들어 일종의 압축 / 압축 해제입니다. (each_line은 일종의 ASCII를 준비하는 것입니다). each_byte?
Jonke

12
while STDIN.gets
  puts $_
end

while ARGF.gets
  puts $_
end

이것은 Perl에서 영감을 얻은 것입니다.

while(<STDIN>){
  print "$_\n"
}

4
간단하고 쉽게 읽을 수 있도록 지옥! 아냐, 잠깐만, 그게 '$ _'이 뭐야? 스택 오버플로에서 영어 를 사용하십시오 !


1

ARGF매개 변수와 함께 사용하려면을 ARGV호출하기 전에 지워야 한다고 추가합니다 ARGF.each. 이것은 ARGF무엇이든 다룰 것이기 때문 입니다ARGV 파일 이름으로 하고 거기에서 행을 먼저 읽기 때문입니다.

다음은 'tee'구현 예입니다.

File.open(ARGV[0], 'w') do |file|
  ARGV.clear

  ARGF.each do |line|
    puts line
    file.write(line)
  end
end

1

나는 이런 식으로 뭔가를 :

all_lines = ""
ARGV.each do |line|
  all_lines << line + "\n"
end
puts all_lines

0

대부분의 답변은 인수가 stdin에 포함되는 내용을 포함하는 파일 이름이라고 가정합니다. 아래의 모든 것은 단지 인수로 취급됩니다. STDIN이 TTY에서 온 경우 무시됩니다.

$ cat tstarg.rb

while a=(ARGV.shift or (!STDIN.tty? and STDIN.gets) )
  puts a
end

인수 또는 stdin이 비어 있거나 데이터가있을 수 있습니다.

$ cat numbers 
1
2
3
4
5
$ ./tstarg.rb a b c < numbers
a
b
c
1
2
3
4
5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.