Ruby: ฉันสามารถเขียนสตริงหลายบรรทัดโดยไม่มีการต่อข้อมูลได้หรือไม่?


397

มีวิธีที่จะทำให้ดูดีขึ้นหรือไม่

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' +
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' +
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

ชอบมีวิธีที่จะบอกเป็นนัยถึงการต่อข้อมูล?


28
ระวังการโจมตีด้วยการฉีด SQL :)
Roy Tinker

คำตอบ:


595

มีชิ้นส่วนของคำตอบนี้ที่ช่วยให้ฉันได้รับสิ่งที่ฉันต้องการ (การต่อหลายบรรทัดแบบง่ายโดยไม่มีช่องว่างพิเศษ) แต่เนื่องจากไม่มีคำตอบจริง ๆ เลยฉันจึงรวบรวมไว้ที่นี่:

str = 'this is a multi-line string'\
  ' using implicit concatenation'\
  ' to prevent spare \n\'s'

=> "this is a multi-line string using implicit concatenation to eliminate spare
\\n's"

เป็นโบนัสนี่คือรุ่นที่ใช้ไวยากรณ์ HEREDOC ตลก (ผ่านลิงก์นี้ ):

p <<END_SQL.gsub(/\s+/, " ").strip
SELECT * FROM     users
         ORDER BY users.id DESC
END_SQL
# >> "SELECT * FROM users ORDER BY users.id DESC"

ส่วนใหญ่จะเป็นสถานการณ์ที่ต้องการความยืดหยุ่นในการประมวลผลมากขึ้น ฉันเองไม่ชอบมันทำให้การประมวลผลในสถานที่แปลก ๆ WRT สตริง (เช่นด้านหน้าของมัน แต่ใช้วิธีการอินสแตนซ์ที่มักจะมาหลังจากนั้น) แต่มันมี โปรดทราบว่าหากคุณกำลังเยื้องEND_SQLตัวระบุสุดท้าย(ซึ่งเป็นเรื่องปกติเนื่องจากนี่อาจจะอยู่ในฟังก์ชั่นหรือโมดูล) คุณจะต้องใช้ไวยากรณ์ยัติภังค์ (นั่นคือp <<-END_SQLแทนp <<END_SQL) มิฉะนั้นช่องว่างที่เยื้องทำให้ตัวระบุถูกตีความว่าเป็นความต่อเนื่องของสตริง

สิ่งนี้ไม่ได้ประหยัดการพิมพ์มากนัก แต่มันดูดีกว่าการใช้เครื่องหมาย + สำหรับฉัน

นอกจากนี้ (ฉันพูดในการแก้ไขหลายปีต่อมา) หากคุณใช้ Ruby 2.3+ ตัวดำเนินการ << ~ ก็มีให้ใช้เช่นกันซึ่งจะเป็นการลบการเยื้องพิเศษออกจากสตริงสุดท้าย คุณควรจะสามารถลบการ.gsubเรียกใช้ในกรณีนั้น (แม้ว่าอาจจะขึ้นอยู่กับทั้งการเยื้องเริ่มต้นและความต้องการขั้นสุดท้ายของคุณ)

แก้ไข: เพิ่มอีกหนึ่ง:

p %{
SELECT * FROM     users
         ORDER BY users.id DESC
}.gsub(/\s+/, " ").strip
# >> "SELECT * FROM users ORDER BY users.id DESC"

2
นี่เป็นคำถามเก่า แต่มีข้อผิดพลาดในคำตอบหรือมีการเปลี่ยนแปลงในไวยากรณ์ตั้งแต่นั้นมา p <<END_SQLควรเป็นอย่างp <<-END_SQLอื่นนี่คือคำตอบ คุณสามารถเลือกที่จะตัดช่องว่างชั้นนำกับผู้ประกอบการ HEREDOC ไก่เขี่ย,<<~END_SQL
jaydel

เป็นเพียงข้อผิดพลาดหากตัวระบุการสิ้นสุดถูกเยื้อง (เครื่องหมายขีดคั่นบอกให้ล่ามทับทิมเพื่อตัดช่องว่างก่อนที่จะทำการกำหนดตัวระบุสิ้นสุด) ฉันสามารถใส่บันทึกที่กล่าวถึงว่า นอกจากนี้ยังมีความจำเป็น ~, gsub \ s + และสตริปเอาช่องว่างชั้นนำแล้ว
A. Wilson

การเพิ่ม<<~คำตอบน่าจะดีจบลงด้วยการค้นคว้าจากที่นั่น Personnally ผมใช้ซึ่งยังแถบสุดท้าย<<~MSG.strip ... MSG \n
Qortex

1
เมื่อฉันเขียนคำตอบนี้ (เก้าปีที่แล้วเชชเชอร์) ทับทิมอยู่ที่ 1.9 และ << ~ (ชัดแจ้ง) ไม่ได้แนะนำจนกระทั่ง 2.3 อย่างไรก็ตามประวัติศาสตร์โบราณกันฉันจะใส่ไว้ในขอบคุณที่นำมันขึ้นมา
A. วิลสัน

ขอบคุณที่เป็นหนึ่งในไม่กี่คำตอบที่ไม่ได้เพิ่มบรรทัดใหม่พิเศษซึ่งเป็นสิ่งที่ฉันพยายามหลีกเลี่ยงเมื่อพบคำถามนี้
Josh

174

ใน ruby ​​2.0 คุณสามารถใช้งานได้ทันที %

ตัวอย่างเช่น:

SQL = %{
SELECT user, name
FROM users
WHERE users.id = #{var}
LIMIT #{var2}
}

14
ใช้งานได้ใน Ruby 1.9.3 เช่นกัน
Andy Stewart

26
สตริงที่สร้างด้วยไวยากรณ์นี้จะรวมทั้งการขึ้นบรรทัดใหม่และการเยื้องใด ๆ ที่เพิ่มในบรรทัดถัดไป
James

มันดีกว่า << EOT ...... EOT (นี่คือเอกสาร)! มันจะทำการแก้ไขหากจำเป็น
Nasser

1
@Nasser heredoc ทำการแก้ไขเช่นกัน
คดีฟ้องร้องกองทุนโมนิก้า

3
หากใช้ Rails ที่เรียกใช้squishเอาต์พุตจะมีประโยชน์
Jignesh Gohel

167

ใช่ถ้าคุณไม่สนใจบรรทัดใหม่ที่ถูกแทรก:

 conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc,
            where etc etc etc etc etc etc etc etc etc etc etc etc etc'

หรือคุณสามารถใช้heredoc :

conn.exec <<-eos
   select attr1, attr2, attr3, attr4, attr5, attr6, attr7
   from table1, table2, table3, etc, etc, etc, etc, etc,
   where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos

87
คุณสามารถใช้%Q(...)
BaroqueBobcat

3
@ Zombies: บรรทัดใหม่มักจะได้รับอนุญาตในคำสั่ง SQL และถือว่าเป็นช่องว่างทั่วไป
Mark Byers

2
ดูคำตอบของฉันด้านล่างสำหรับตัวอย่างคุณสามารถใช้% ได้ทันที
Robbie Guilfoyle

4
คุณสามารถใช้%(...)
zero-divisor

1
สิ่งสำคัญที่ต้องจำไว้ถ้าคุณตั้งใจเพิ่มช่องว่างต่อท้ายและใช้หนึ่งในโซลูชันเหล่านี้คือตัวแก้ไขของคุณอาจลบพื้นที่ต่อท้ายโดยอัตโนมัติเมื่อบันทึกไฟล์ ในขณะที่ฉันชอบพฤติกรรมนี้ตามปกติมันทำให้เกิดปัญหาที่ไม่คาดคิดสำหรับฉันสองสามครั้ง วิธีแก้ไขคือเขียนสตริงหลายบรรทัดเหมือนที่ OP ทำในคำถาม
Dennis

50

มีหลายไวยากรณ์สำหรับสตริงหลายบรรทัดตามที่คุณได้อ่านไปแล้ว สิ่งที่ฉันชอบคือสไตล์ Perl:

conn.exec %q{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
      from table1, table2, table3, etc, etc, etc, etc, etc,
      where etc etc etc etc etc etc etc etc etc etc etc etc etc}

สตริงหลายบรรทัดเริ่มต้นด้วย% q ตามด้วย {, [หรือ (และจากนั้นถูกยกเลิกโดยอักขระที่กลับด้านที่สอดคล้องกัน% q ไม่อนุญาตการแก้ไข)% Q ทำเช่นนั้นคุณสามารถเขียนสิ่งนี้:

conn.exec %Q{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
      from #{table_names},
      where etc etc etc etc etc etc etc etc etc etc etc etc etc}

จริง ๆ แล้วฉันไม่รู้เลยว่าการเรียกใช้สตริงหลายสายเหล่านี้ได้อย่างไรเราเรียกมันว่า Perl multilines

อย่างไรก็ตามโปรดทราบว่าไม่ว่าคุณจะใช้ Perl multilines หรือ heredocs ตามคำแนะนำของ Mark and Peter คุณจะพบกับช่องว่างที่ไม่จำเป็น ทั้งในตัวอย่างของฉันและตัวอย่างของพวกเขาบรรทัด "จาก" และ "ที่" มีช่องว่างนำหน้าเนื่องจากการเยื้องในโค้ด หากไม่ต้องการช่องว่างนี้คุณต้องใช้สตริงที่ต่อกันตามที่คุณกำลังทำอยู่


4
จาก # {table_names} จะไม่ทำงานในตัวอย่างนี้เมื่อคุณใช้% q {} มันจะใช้ได้ถ้าคุณใช้% q [] หรือ ()
MatthewFord

2
ที่ชื่นชอบในหลอดเลือดดำนี้เป็นเพียง% {สตริงหลายซุปเปอร์ด้วยการสนับสนุนการแก้ไข}
ดยุค

สตริงที่สร้างขึ้นจาก%qตระกูลจะรวมถึงบรรทัดใหม่ที่ไม่เท่าเทียมกับรหัสต้นฉบับ
Josh

29

บางครั้งก็ควรลบอักขระบรรทัดใหม่\nเช่น:

conn.exec <<-eos.squish
 select attr1, attr2, attr3, attr4, attr5, attr6, attr7
 from table1, table2, table3, etc, etc, etc, etc, etc,
 where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos

5
นี่คือรางรถไฟที่ไม่ใช่ทับทิม
a14m

23

คุณยังสามารถใช้เครื่องหมายคำพูดคู่

x = """
this is 
a multiline
string
"""

2.3.3 :012 > x
 => "\nthis is\na multiline\nstring\n"

หากต้องการลบตัวแบ่งบรรทัด "\ n" ใช้แบ็กสแลช "\" ที่ท้ายบรรทัดแต่ละบรรทัด


5
คุณสามารถได้ผลลัพธ์เดียวกันโดยใช้เครื่องหมายคำพูดคู่ ไม่มีสิ่งเช่นทับทิมสองคำพูดใน "" + "double quotes with some content" + ""มันก็ตีความพวกเขาเป็น
rakvium

ใช่ แต่ `" "+" \ n hello \ n "+" "ดูแปลก ๆ
juliangonzalez

1
ใช่มันดูแปลกและนี่คือเหตุผลว่าทำไมไม่มีเหตุผลที่จะเพิ่มเครื่องหมายคำพูดคู่พิเศษเมื่อคุณสามารถใช้เครื่องหมายคำพูดคู่เอกพจน์กับผลลัพธ์เดียวกันได้
rakvium

ใช่ฉันหมายถึงเครื่องหมายบวก เครื่องหมายอัญประกาศคู่ที่ไม่ได้ดูดีสามารถอ่านได้และง่ายกว่าที่จะมองเห็นแทนที่จะเป็นเครื่องหมายคำพูดเดี่ยวซึ่งควรใช้กับสตริงบรรทัดเดียว
juliangonzalez

1
ฉันหมายถึงว่ามัน"x"ดูดีขึ้นและทำงานได้เร็วกว่า"""x"""(ซึ่งโดยทั่วไปจะเหมือนกับ""+"x"+"") หรือ"""""x"""""(ซึ่งก็เหมือนกับ"" + "" + "x" + "" + "") มันคือ Ruby ไม่ใช่ Python ที่คุณใช้"""แทน"เมื่อคุณต้องการสตริงหลายบรรทัด
rakvium

15
conn.exec = <<eos
  select attr1, attr2, attr3, attr4, attr5, attr6, attr7
  from table1, table2, table3, etc, etc, etc, etc, etc,
  where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos

1
การใช้ heredoc โดยไม่มี '-' ดังเช่นใน '<< - eos' จะรวมช่องว่างของผู้นำเพิ่มเติม เห็นการตอบสนองของ Mark Byers
59

heredoc จะรวมถึงการขึ้นบรรทัดใหม่ซึ่งไม่เทียบเท่ากับรหัสต้นฉบับ
Josh

15

ตัวเลือกอื่น:

#multi line string
multiline_string = <<EOM
This is a very long string
that contains interpolation
like #{4 + 5} \n\n
EOM

puts multiline_string

#another option for multiline string
message = <<-EOF
asdfasdfsador #{2+2} this month.
asdfadsfasdfadsfad.
EOF

puts message

1
ควรเปลี่ยน<<EOMเป็น<<-EOMไม่ใช่หรือ?
kingPuppy

บางทีมันอาจดูเหมือนเป็น<<-EOFตัวอย่างสำหรับฉัน ฉันเดาว่าวิธีใดก็ใช้ได้
Alex Cohen

heredoc จะรวมถึงการขึ้นบรรทัดใหม่ซึ่งไม่เทียบเท่ากับรหัสต้นฉบับ
Josh

11

เมื่อเร็ว ๆ นี้ด้วยคุณสมบัติใหม่ใน Ruby 2.3 ใหม่squiggly HEREDOCจะช่วยให้คุณเขียนสตริงหลายบรรทัดของเราในลักษณะที่ดีกับการเปลี่ยนแปลงที่น้อยที่สุดดังนั้นการใช้สิ่งนี้ร่วมกับ.squish(ถ้าคุณกำลังใช้ราง) จะช่วยให้คุณเขียน multiline ในวิธีที่ดี! ในกรณีที่มีเพียงแค่ใช้ทับทิมที่คุณสามารถทำได้<<~SQL.split.join(" ")ซึ่งเป็นเกือบเดียวกัน

[1] pry(main)> <<~SQL.squish
[1] pry(main)*   select attr1, attr2, attr3, attr4, attr5, attr6, attr7
[1] pry(main)*   from table1, table2, table3, etc, etc, etc, etc, etc,
[1] pry(main)*   where etc etc etc etc etc etc etc etc etc etc etc etc etc
[1] pry(main)* SQL
=> "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 from table1, table2, table3, etc, etc, etc, etc, etc, where etc etc etc etc etc etc etc etc etc etc etc etc etc"

อ้างอิง: https://infinum.co/the-capsized-eight/multiline-strings-ruby-2-3-0-the-squiggly-heredoc


Squish เป็นรางไม่ใช่ทับทิม
Josh

1
@ Josh, ใช่คุณพูดถูก, ปรับปรุงคำตอบ, ไชโย
Mark Jad

6
conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' <<
        'from table1, table2, table3, etc, etc, etc, etc, etc, ' <<
        'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

<< เป็นตัวดำเนินการเรียงต่อกันสำหรับสตริง


2
+เป็นตัวดำเนินการเรียงต่อกันแบบปกติ<<คือตัวดำเนินการผนวกแบบแทนที่ การใช้ผลข้างเคียงกับตัวอักษรจะเกิดขึ้นที่นี่ (สตริงแรกมีการแก้ไขสองครั้งและส่งคืน) แต่ IMHO มันแปลกและทำให้ฉันทำสองครั้งซึ่ง+จะชัดเจนอย่างสมบูรณ์ แต่บางทีฉันแค่เพิ่งรู้จัก Ruby ...
Beni Cherniavsky-Paskin

สิ่งนี้จะไม่ทำงานหากfrozen_string_literalเปิดใช้งาน
Raido

6

ถ้าคุณทำจิตใจพื้นที่พิเศษและการขึ้นบรรทัดใหม่คุณสามารถใช้

conn.exec %w{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
  from table1, table2, table3, etc, etc, etc, etc, etc,
  where etc etc etc etc etc etc etc etc etc etc etc etc etc} * ' '

(ใช้% W สำหรับสตริงที่สอดแทรก)


ฉันชอบอันนี้มากเพราะมันช่วยให้ผสมผสานการใช้งานได้มากขึ้น
schmijos

1
วิธีนี้จะบีบช่องว่างที่อยู่ติดกันหลายแห่งให้เป็นหนึ่งเดียว (squishing ของการขึ้นบรรทัดใหม่ + การเยื้องต่อไปนี้เป็นการชนะที่นี่ แต่ในช่วงกลางของบรรทัดมันอาจจะน่าแปลกใจ)
Beni Cherniavsky-Paskin

5

เพื่อหลีกเลี่ยงการปิดวงเล็บสำหรับแต่ละบรรทัดคุณสามารถใช้เครื่องหมายคำพูดคู่กับแบ็กสแลชเพื่อหลีกเลี่ยงการขึ้นบรรทัดใหม่:

"select attr1, attr2, attr3, attr4, attr5, attr6, attr7 \
from table1, table2, table3, etc, etc, etc, etc, etc, \
where etc etc etc etc etc etc etc etc etc etc etc etc etc"

นี่คือหนึ่งในไม่กี่คำตอบในหน้านี้ซึ่งตอบคำถามได้จริง!
Josh

4
conn.exec [
  "select attr1, attr2, attr3, ...",
  "from table1, table2, table3, ...",
  "where ..."
].join(' ')

ข้อเสนอแนะนี้มีข้อได้เปรียบเหนือที่นี่เอกสารและสตริงยาว ๆ ที่ตัวเยื้องอัตโนมัติสามารถเยื้องส่วนของสตริงได้อย่างเหมาะสม แต่มันมาในราคาที่มีประสิทธิภาพ


@Aidan คุณสามารถแทนที่เครื่องหมายจุลภาคด้วยเครื่องหมายแบ็กสแลช (a la C) และไม่จำเป็นต้องเข้าร่วม (หรืออาร์เรย์): ล่ามจะต่อสายอักขระที่เวลา (ฉันคิดว่า) แยกวิเคราะห์ทำให้ค่อนข้างเร็วเมื่อเทียบกับทางเลือกส่วนใหญ่ . อย่างไรก็ตามข้อดีอย่างหนึ่งของการเข้าร่วมอาร์เรย์ของสตริงคือการที่ตัวกดอัตโนมัติบางตัวทำงานได้ดีกว่าที่ทำกับสตริงที่นี่ doc หรือกับ \
Wayne Conrad

1
One note, ไวยากรณ์ heredoc << - จะช่วยให้การเยื้องที่เหมาะสม
A. วิลสัน

2

Ruby-way (TM) ตั้งแต่ Ruby 2.3: ในการกำหนดสตริงหลายบรรทัดพร้อมกับการขึ้นบรรทัดใหม่และการระบุที่เหมาะสมให้ใช้ HEREDOC อย่างช้าๆ <<~ :

conn.exec <<~EOS
            select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc
            where etc etc etc etc etc etc etc etc etc etc etc etc etc
          EOS

# -> "select...\nfrom...\nwhere..."

หากการระบุที่ถูกต้องไม่ใช่ข้อกังวลราคาอัญประกาศเดี่ยวและคู่สามารถขยายหลายบรรทัดใน Ruby:

conn.exec "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 
           from table1, table2, table3, etc, etc, etc, etc, etc, 
           where etc etc etc etc etc etc etc etc etc etc etc etc etc"    

# -> "select...\n           from...\n           where..."

หากเครื่องหมายคำพูดเดี่ยวหรือคู่มีความยุ่งยากเพราะจะต้องมีการหลีกหนีจำนวนมากดังนั้นสัญกรณ์ตัวอักษรร้อยละสตริง%เป็นโซลูชั่นที่มีความยืดหยุ่นมากที่สุด:

conn.exec %(select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc
            where (ProductLine = 'R' OR ProductLine = "S") AND Country = "...")
# -> "select...\n            from...\n            where..."

หากจุดประสงค์คือการหลีกเลี่ยงการขึ้นบรรทัดใหม่ (ซึ่งทั้ง HEREDOC ไก่เขี่ยคำพูดและสตริงตัวอักษรร้อยละจะทำให้เกิด) แล้วเครื่องหมายทับขวาเป็นตัวละครที่ไม่ใช่ช่องว่างที่ผ่านมาจะดำเนินการต่อบรรทัดและจะทำให้ทับทิมเพื่อเชื่อมสตริงกลับ (ระวังช่องว่างเหล่านั้นภายในสตริงที่ยกมา):

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' \
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' \
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

# -> "select...from...where..."

หากคุณใช้ Rails String.squishจะดึงสตริงของพื้นที่นำหน้าและส่วนท้ายและยุบช่องว่างที่ต่อเนื่องกันทั้งหมด (ขึ้นบรรทัดใหม่แท็บและทั้งหมด) ลงในพื้นที่เดียว:

conn.exec "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 
           from table1, table2, table3, etc, etc, etc, etc, etc, 
           where etc etc etc etc etc etc etc etc etc etc etc etc etc".squish

# -> "select...from...where..."

รายละเอียดเพิ่มเติม:

Ruby HEREDOC ไวยากรณ์

นี่เอกสารสัญกรณ์สำหรับ Strings ทำงานเป็นวิธีการกำหนดบล็อคข้อความยาวแบบอินไลน์ในรหัส มันเริ่มต้น<<แล้วตามด้วยสตริงที่ผู้ใช้กำหนด (End of String terminator) บรรทัดต่อไปนี้ทั้งหมดถูกต่อกันจนกว่าจะพบจุดสิ้นสุดของจุดสิ้นสุดที่จุดเริ่มต้นของบรรทัด:

puts <<HEREDOC 
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"

สามารถเลือก End terminator ได้อย่างอิสระ แต่เป็นเรื่องปกติที่จะใช้ "EOS" (End of String) หรือสิ่งที่ตรงกับโดเมนของ String เช่น "SQL"

HEREDOC รองรับการแก้ไขโดยค่าเริ่มต้นหรือเมื่อมีการอ้างถึงจุดสิ้นสุด EOS สองครั้ง:

price = 10
print <<"EOS"  # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."

การแก้ไขสามารถปิดการใช้งานได้หากมีการยกระดับจุดสิ้นสุดของกล้อง EOS:

print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."

ข้อ จำกัด ที่สำคัญอย่างหนึ่งของ<<HEREDOCคือการสิ้นสุดของจุดสิ้นสุดของสตริงต้องอยู่ที่จุดเริ่มต้นของบรรทัด:

  puts <<EOS 
    def foo
      print "foo"
    end
  EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS

ในการหลีกเลี่ยงปัญหานี้<<-ไวยากรณ์ถูกสร้างขึ้น จะช่วยให้ตัวคั่นกล้อง EOS ถูกเยื้องเพื่อทำให้โค้ดดูดีขึ้น เส้นแบ่งระหว่าง<<-และจุดสิ้นสุด EOS ยังคงใช้ในการขยายแบบเต็มรวมถึงการเยื้องทั้งหมด:

puts <<-EOS # Use <<- to indent End of String terminator
  def foo
    print "foo"
  end
EOS
# -> "..def foo\n....print "foo"\n..end"

ตั้งแต่ Ruby 2.3 ตอนนี้เรามี HEREDOC อย่างลบล้าง<<~ช่องว่างชั้นนำ:

puts <<~EOS # Use the squiggly HEREDOC <<~ to remove leading whitespace (since Ruby 2.3!)
  def foo
    print "foo"
  end
EOS
# -> "def foo\n..print "foo"\nend"

บรรทัดว่างและบรรทัดที่มีแท็บและพื้นที่ว่างเท่านั้นจะถูกละเว้นโดย << ~

puts <<~EOS.inspect 
  Hello

    World!
EOS
#-> "Hello\n..World!"

หากใช้ทั้งแท็บและช่องว่างแท็บนั้นจะถือว่าเท่ากับ 8 ช่องว่าง หากบรรทัดที่เยื้องน้อยที่สุดอยู่ตรงกลางแท็บแท็บนี้จะไม่ถูกลบ

puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"

HEREDOC สามารถทำสิ่งที่บ้าบางอย่างเช่นการดำเนินการคำสั่งโดยใช้ backticks:

puts <<`EOC`            
echo #{price}
echo #{price * 2}
EOC

คำจำกัดความของสตริง HEREDOC สามารถ "เรียงซ้อน" ซึ่งหมายความว่าตัวสิ้นสุดของกล้อง EOS ตัวแรก (EOSFOO ด้านล่าง) จะจบสายตัวแรกและเริ่มต้นตัวที่สอง (EOSBAR ด้านล่าง):

print <<EOSFOO, <<EOSBAR    # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR

ฉันไม่คิดว่าจะมีใครใช้มันเป็นเช่นนี้ แต่<<EOSจริงๆแล้วเป็นเพียงตัวอักษรสตริงและสามารถใส่ได้ทุกที่ที่สามารถใส่สตริงได้:

def func(a,b,c)
  puts a
  puts b
  puts c
end

func(<<THIS, 23, <<THAT) 
Here's a line
or two.
THIS
and here's another.
THAT

หากคุณไม่มี Ruby 2.3 แต่ Rails >=3.0 คุณสามารถใช้String.strip_heredocซึ่งเหมือนกับ<<~

# File activesupport/lib/active_support/core_ext/string/strip.rb, line 22
class String
  def strip_heredoc
    gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
  end
end

puts <<-USAGE.strip_heredoc # If no Ruby 2.3, but Rails >= 3.0
  This command does such and such.

  Supported options are:
    -h         This message
    ...
USAGE

เปอร์เซ็นต์ตัวอักษรสตริง

ดูRubyDocสำหรับวิธีการใช้เครื่องหมายเปอร์เซ็นต์ตามด้วยสตริงในวงเล็บเป็นคู่เช่น%(...), %[...], %{...}ฯลฯ หรือคู่ของตัวอักษรใด ๆ ที่ไม่ใช่ตัวเลขเช่น%+...+

คำสุดท้าย

สุดท้ายเพื่อให้ได้คำตอบสำหรับคำถามเดิม "มีวิธีการเรียงต่อกันหรือไม่" คำตอบ: Ruby หมายถึงการเรียงต่อกันเสมอหากพบสองสตริง (single และ double ที่ยกมา) ที่พบกลับไปด้านหลัง:

puts "select..." 'from table...' "where..."
# -> "select...from table...where..."

ข้อแม้คือสิ่งนี้ใช้ไม่ได้กับการแบ่งบรรทัดเนื่องจาก Ruby แปลความหมายของคำแถลงจุดสิ้นสุดและบรรทัดที่ตามมาของการใช้คำสั่งเพียงอย่างเดียวบนบรรทัดไม่ได้ทำอะไรเลย


1

คำตอบที่สง่างามวันนี้:

<<~TEXT
Hi #{user.name}, 

Thanks for raising the flag, we're always happy to help you.
Your issue will be resolved within 2 hours.
Please be patient!

Thanks again,
Team #{user.organization.name}
TEXT

มีความแตกต่างค่ะ <<-TEXTและ<<~TEXTอดีตรักษาระยะห่างภายในบล็อกและหลังไม่ได้

มีตัวเลือกอื่น ๆ เช่นกัน เช่นเดียวกับการเรียงต่อกันเป็นต้น แต่อันนี้ก็สมเหตุสมผลกว่าโดยทั่วไป

หากฉันผิดที่นี่ให้ฉันรู้ว่า ...


heredoc จะรวมถึงการขึ้นบรรทัดใหม่ซึ่งไม่เทียบเท่ากับรหัสต้นฉบับ
Josh

1

เช่นเดียวกับคุณฉันกำลังมองหาวิธีแก้ปัญหาซึ่งไม่รวมถึงการขึ้นบรรทัดใหม่ไม่รวมถึงการขึ้นบรรทัดใหม่(แม้ว่าพวกเขาอาจจะปลอดภัยใน SQL แต่พวกเขาก็ไม่ปลอดภัยในกรณีของฉันและฉันมีกลุ่มข้อความจำนวนมากที่จะจัดการกับ)

นี่เป็นเนื้อหาที่น่าเกลียด แต่คุณสามารถ backslash-escape บรรทัดใหม่ใน heredoc เพื่อตัดพวกเขาออกจากสตริงผลลัพธ์:

conn.exec <<~END_OF_INPUT
    select attr1, attr2, attr3, attr4, attr5, attr6, attr7 \
    from table1, table2, table3, etc, etc, etc, etc, etc, \
    where etc etc etc etc etc etc etc etc etc etc etc etc etc
  END_OF_INPUT

โปรดทราบว่าคุณไม่สามารถครบกำหนดได้หากไม่มีการแก้ไข (IE <<~'END_OF_INPUT') ดังนั้นโปรดระมัดระวัง #{expressions}จะถูกประเมินที่นี่ในขณะที่พวกเขาจะไม่อยู่ในรหัสต้นฉบับของคุณ A. คำตอบของวิลสันอาจดีกว่าด้วยเหตุผลนั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.