Ruby One-Liners

From Here

翻轉每一行

輸入資料:

1
2
3
4
$ cat foo
qwe
123
bar

翻轉每一行的字:

1
2
3
4
$ ruby -e 'File.open("foo").each_line { |l| puts l.chop.reverse }'
ewq
321
rab

從 stdout 翻轉每一行的字:

1
cat foo | ruby -e 'while s = gets; puts s.chop.reverse; end'

翻轉所有 ARGF == $<:

1
2
cat foo | ruby -e 'ARGF.each_line { |l| puts l.chop.reverse }'
ruby -e 'ARGF.each_line { |l| puts l.chop.reverse }' foo

自動使用迴圈:

1
ruby -ne 'puts $_.chop.reverse' foo

每個迴圈最後自動輸出 $_ 的內容:

1
ruby -pe '$_.chop!.reverse!; $_ += "\n"' foo

自動刪除行尾的換行字元:

1
ruby -lpe '$_.reverse!' foo

輸出新的檔案:

1
2
3
4
5
6
7
8
9
$ cat foo
qwe
123
bar
$ ruby -i -lpe '$_.reverse!' foo
$ cat foo
ewq
321
rab

縮排

像這樣:

1
cat example.rb | ruby -ne 'puts " " * 4 + $_'
1
ruby -ne 'puts " " * 4 + $_' example.rb

加上行號 (所有檔案)

1
ruby -ne 'puts "#$. #$_"' foo.rb bar.rb

加上行號 (單一檔案)

1
ruby -ne '$. = 1 if $<.pos - $_.size == 0; puts "#$. #$_"' foo.rb bar.rb

字數統計

1
ruby -ane 'w = (w || 0) + $F.size; END { p w }' exmpl.txt

刪除空白行

刪除文件中的所有連續的空白行,除了每個組中的第一個

1
ruby -ne 'puts $_ if /^[^\n]/../^$/'

取出註解

輸入:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat comments.txt
some code
/*
comment one
comment two
*/
more code
/* one-line comment */
a bit more code
/*
comment three
*/
even more code

動作:

1
2
3
4
5
6
7
8
9
$ ruby -ne 'puts $_ if ($_ =~ /^\/\*/)..($_ =~ /\*\/$/)' comments.txt
/*
comment one
comment two
*/
/* one-line comment */
/*
comment three
*/
1
ruby -pe 'next unless ($_ =~ /^\/\*/)..($_ =~ /\*\/$/)' comments.txt

Homebrew flip-flop (from “The Ruby programming language” by David Flanagan, Yukihiro Matsumoto):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# flip-flop.rb
$state = false
def flipflop(s)
unless $state
result = (s =~ /^\/\*$/)
if result
$state = !(s =~ /^\*\/$/)
end
result
else
$state = !(s =~ /^\*\/$/)
true
end
end

ARGF.each_line do |l|
puts l if flipflop(l)
end

Try it:

1
ruby flip-flop.rb comments.txt

標記行末空格

1
ruby -lpe '$_.gsub! /(\s+)$/, "\e[41m\\1\e[0m"' example.rb

移除行末空格

1
ruby -lpe '$_.rstrip!' example.rb

每行出過 50 字則標記顏色

簡單的方法:

1
ruby -ne 'puts "#{$_}\e[31m#{$_.chop!.slice!(50..-1)}\e[0m"' example.rb

難懂但好傳遞參數:

1
ruby -e 'w = $*.shift; $<.each { |l| puts "#{l}\e[31m#{l.chop!.slice!(w.to_i..-1)}\e[0m" }' 50 example.rb

簡單的 REPL

最直接的一種方法:

1
ruby -e  'loop { puts eval(gets) }'

加上 -n 選項:

1
ruby -ne 'puts eval($_)'

>> 提示符號,但第一行沒有:

1
ruby -ne 'print "#{eval($_).inspect}\n>> "'

修正:

1
ruby -ne 'BEGIN{print">> "}; print "#{eval($_).inspect}\n>> "'

REPL 結束時的回覆:

1
ruby -ne 'BEGIN{print">> "}; print "#{eval($_).inspect}\n>> "; END{puts "Bye"}'

支援 RuntimeError,但不包括 SyntaxError:

1
ruby -ne 'BEGIN{print">> "}; print "#{(eval($_) rescue $!).inspect}\n>> "; END{puts "Bye"}'

Rescue 所有錯誤 – 拯救世界:

1
ruby -ne 'BEGIN{print">> "}; print "#{(begin; eval($_); rescue Exception; $!; end).inspect}\n>> "; END{puts "Bye"}'

額外

在每個檔案前加上版權:

1
2
3
4
5
6
7
8
9
10
11
12
# copyright.rb
copyright = DATA.read

ARGF.each_line do |l|
puts copyright if $. == 1
puts l
end

__END__
####################################
# Copyright (C) 2012 Kirill Lashuk #
####################################

使用方法:

1
ruby copyright.rb foo.py > foo2.py

取代的方法:

1
ruby -i copyright.rb foo.py

選擇性的方法:

1
2
3
4
5
6
7
8
9
10
# copyright2.rb
BEGIN { copyright = DATA.read }

puts copyright if $. == 1

__END__
####################################
# Copyright (C) 2012 Kirill Lashuk #
####################################

取代後且備份原始檔:

1
2
3
4
5
6
7
8
9
10
11
$ cat bar.py
print 'hello'
$ ruby -p -i.bak copyright2.rb bar.py
$ cat bar.py
####################################
# Copyright (C) 2012 Kirill Lashuk #
####################################

print 'hello'
$ cat bar.py.bak
print 'hello'

Links