ในโพสต์นี้เราจะพูดถึง escaping characters ใน Ruby เราจะเรียนรู้วิธี escape characters ยังไง มันทำงานยังไง และหลีกเลี่ยง escaping เลยสำหรับบาง use cases หากคิดว่าคุณรู้ทั้งหมดเกี่ยวกับ \ อ่านจบและประหลาดใจ...
มาดำน้ำลึกกับ character escaping ใน strings เลย
Escaping Quotes
เมื่อใช้ strings ใน Ruby เราบางครั้งต้องใส่ quote ที่ใช้ define string เข้าไปใน string เอง เมื่อทำเราสามารถ escape quote character ด้วย backslash \ symbol
# Escape quotes in double quoted strings
"Hello \"world\"!" => "Hello \"world\"!"
# Escape quotes in single quoted strings
'Hello \'world\'!' => "Hello 'world'!"
ที่นี่เราเห็นว่า Ruby default เป็น double quoted strings สำหรับ output และ escape double quotes เฉพาะใน output
Escape Sequences
นอกจาก quotes มี symbols อื่นๆ ที่ escape ใน strings ได้ ตัวอย่าง newline represented by \n เรียกว่า "escape sequence"
"Hello\nworld" => "Hello\nworld"
สิ่งที่คืนคือ string เดียวกับที่เราสร้าง แต่เห็นว่า \n highlighted บ่งบอกว่าเป็น escape sequence หากเรา print string นี้ตอนนี้ เราจะเห็นว่า literal \n ไม่พิมพ์ แต่ actual newline พิมพ์แทน
puts "Hello\nworld"
=> Hello
world
สิ่งนี้ไม่ทำงานใน single quoted strings \n sequence interpreted as literal \n ใน double quoted strings คุณต้อง escape backslash symbol เพื่อได้ผลเดียวกัน
'\n' => "\\n"
ตัวอย่าง escape sequences อื่นๆ ทำงานเหมือนกัน: \t, \s และ \b แทน tab, space และ backspace ตามลำดับ
Single quotes vs and double quotes
ความแตกต่างระหว่าง single และ double quoted strings ใน Ruby คือวิธี string definitions represent escape sequences
- ใน double quoted strings คุณเขียน escape sequences และ Ruby จะ output translated meaning
\nกลายเป็น newline - ใน single quoted strings แต่ escape sequences ถูก escape และคืน literal definition
\nคงเป็น\n
ทั้งสอง string types มี use cases ของตัวเอง แน่นอน คุณน่าจะใช้ double quoted strings พร้อม escape sequences ใช้ translated meaning เช่น newline หรือ tab
Single quotes มีประโยชน์สำหรับหลีกเลี่ยง escaping escape sequences เอง เหมาะสำหรับ demonstrate usage หรือหลีกเลี่ยง accidentally using escape sequences ที่ไม่ได้ตั้งใจ
puts "Line 1\nLine 2"
=> Line 1
Line 2
puts 'Using a \n we can indicate a newline.'
=> Using a \n we can indicate a newline.
Escaping Interpolation
Ruby รองรับ interpolation ภายใน strings แต่ไม่ใช่ทุก string definitions เท่าเทียม Interpolation ทำงานได้แค่ใน double quoted strings
ใน code example ด้านล่าง เราเห็น interpolation ทำงานใน double quoted string แต่ Ruby escape interpolation sequence ใน single quoted string ทำให้มัน useless
name = "world"
"Hello #{name}" => "Hello world"
'Hello #{name}' => "Hello \#{name}"
Behavior นี้ apply ให้เกือบทุกประเภท string "magic" Double quotes รองรับ single quotes ไม่รองรับ
Percent notation for String
Percent notation ใน Ruby เป็นสิ่ง inspired by Perl programming language ให้เรา shorthands มากสำหรับ common type definitions
Behavior เดียวกันสำหรับ single และ double quoted strings apply ให้ percent notation ด้วย
%()และ%Q()behave เหมือน double quoted string%q()behave เหมือน single quoted string
ปัญหากับ percent notation คือคุณต้อง escape parenthesis characters () แทน quotes เมื่อ parenthesis ไม่ balanced
ซึ่งเป็นเหตุผล Ruby allow ใช้ symbols อื่นๆ สำหรับ percent notation ได้: %[foo], %{foo}, %-foo-, %?foo?, etc. มันแม้รองรับ %"foo" และ %'foo'
ที่นี่เราเห็นว่า Ruby escape string ให้เราเมื่อใช้ percent notation
%(Hello "world"!) => "Hello \"world\"!"
# With unbalanced parenthesis
%(Hello world\)!) => "Hello world)!"
# With balanced parenthesis
%(Hello (world)!) => "Hello (world)!"
อีกครั้ง rules เดียวกัน apply ที่นี่เหมือน normal single และ double quoted strings Escape sequences และ interpolation escaped by default ใน single quoted strings
name = "world"
%(Hello\n "#{name}"!) => "Hello\n \"world\"!"
%q(Hello\n "#{name}"!) => "Hello\\n \"\#{name}\"!"
%Q(Hello\n "#{name}"!) => "Hello\n \"world\"!"
Escaping Characters in Regular Expressions
Escaping characters ทำงานใน regular expressions ด้วย ใน regular expressions หลาย characters represent มากกว่าแค่ literal definition
. เป็น wild card สำหรับ any character brackets [] represent range หรือ selection parenthesis () match expression etc. เพื่อใช้ literal definitions เราสามารถ escape ด้วย backslash symbol
/Hello \[world\]/ => /Hello \[world\]/
/\[world\]/ =~ "Hello [world]" => 6
หากเราไม่ escape brackets มันจะหา any characters ระหว่าง brackets แทน และหา first match ใน character l ใน "Hello" ตำแหน่ง 3
/[world]/ =~ "Hello [world]" => 2 # zero index
เพื่อหลีกเลี่ยงต้อง escape forward slash symbol / ใช้ define regular expression เราสามารถใช้ percent notation อีกแบบ
%r{/world/} => /\/world\//
ใช้ %r{} เรา define regular expression ที่ไม่ต้อง escape forward slash ใน result เราเห็นว่า Ruby escape forward slash ให้เรา
Escaping Line Breaks
ก่อนหน้านี้เรา escape "newline" escape sequence \n ใน string ใน Ruby คุณรู้ไหมว่าคุณ escape line break ใน Ruby เองได้?
ตัวอย่าง เรามี very long line สำหรับ method call และมัน break code style guide's max line length
ruby_method_with_many_arguments "Hello world", split: " ", join: "\n"
เราสามารถวาง arguments บน separate lines ทำให้แต่ละ line สั้นกว่า ทำงานตราบเท่าที่ previous line จบด้วย comma ,, operators เช่น plus symbol +, หรือเป็นส่วนของ method call wrapped in parenthesis ()
ruby_method_with_many_arguments "Hello world", split: " ", join: "\n"
ruby_method_with_many_arguments(
"Hello world",
split: " ",
join: "\n"
)
หากเราอยาก align all arguments บน indentation level เดียวกันโดยไม่ wrap ใน parenthesis () เราสามารถใช้ backslash \ escape line break
ruby_method_with_many_arguments \
my_string, split: " ", join: "\n"
สิ่งที่เราทำที่นี่ไม่ได้บอก Ruby escape newline จริงๆ แต่ว่า statement จะ continue บน next line
Escaping Line Breaks in String Definitions
Escape line ending ทำงานสำหรับ string definitions ด้วย ปกติหากเรามี multi-line string เราใช้ plus symbol + combine strings บน two lines
"foo" + "bar" => "foobar"
นี่สร้าง two strings บน two lines แล้ว combine เป็น one จริงๆ สร้าง three string objects
แทนที่จะใช้ plus symbol เราสามารถ escape line break ด้วย backslash อีกครั้ง
"foo" \ "bar" => "foobar"
Result เหมือนกัน หรือเปล่า?
ในตัวอย่างแรก เรา actually combine two new strings ในขณะที่ตัวอย่างที่สอง Ruby จะสร้างแค่ one Ruby interpreter จะเห็น backslash \ as continuation ของ string definition และสร้างแค่ one string จาก two lines ดังนั้นมัน even better สำหรับ app's memory usage
Conclusion
Escaping characters ใน Ruby และหลาย programming languages อาจ confusing คุณอย่างกะทันหัน certain combinations of characters ได้ different meaning ภายใน double quoted string เทียบกับใช้ใน single quoted string
หวังว่า little guide นี้ช่วยคุณเข้าใจวิธี properly escape characters และ sequences ใน Ruby ความแตกต่างระหว่าง double และ single quoted string เป็น key ที่นี่
String "magic" ของ escape sequences และ interpolation ทำงานจริงใน double quoted strings เท่านั้น ไม่ใช่ใน single quoted strings
มี other ways escape code ใน Ruby เช่นกัน Percent notation ช่วยหลีกเลี่ยง escape certain characters ตลอดเวลา ใน strings และ regular expressions
แต่ backslash ยัง useful สำหรับเขียน multi-line strings และ continue line of Ruby code ไป next line อะไรที่ฉันใช้เยอะเพื่อให้ code clean และ readable
บอกเราที่ @AppSignal หากอยากรู้เพิ่ม หรือมีคำถามเฉพาะเกี่ยว escaping characters ใน Ruby
Fun side-note: สำหรับ post นี้ เขียนใน Markdown ฉันต้องใช้ backslash symbol เยอะ คล้ายกับ Ruby Markdown allow escaping certain characters ปกติใน Markdown คุณไม่ wrap backslash ใน code block ได้ เพราะมัน escape code block เอง แทนที่ฉัน escape space แทน
`\` # Doesn't work
`\ ` # Works :)