在 Tcl 中加入包含希伯来语的列表?

Joing lists containing Hebrew in Tcl?

我正在使用 Tcl 8.6.11、SQLite 3.35.5 和 Manjaro Linux KDE。

我正在尝试用希伯来语写一节经文,并在数据 table 中每行写一个词。这是一 例如,诗歌。

בְּרֵאשִׁית בָּוָא אֱלֹהִים אֵת הַשּׁמַיִם וְאֵת הָאָֽוֶץ

目标是将数据写入列表,然后作为 SQL 插入语句的值部分加入列表。如您所见,每个 [lindex $l n] 都按预期打印,但是从第二个元素开始的 [join $l ,] 将希伯来语放在第一个位置而不是最后一个位置,导致 SQL 语句失败。

如何让 [join $l ,] 的每个组件都按它们在 [lindex $l n] 中的顺序排序?

谢谢。

set l {}
set sql { select * from src_original where type_no=0 and book_no < 40 limit 1}
dbws eval $sql origLang {
  set i 0
  foreach { x } $origLang(original) { lappend l "($origLang(book_no),$origLang(chapter_no),$origLang(verse_no),[incr i],$x)" }
}

puts [lindex $l 0]; # (1,1,1,1,בְּרֵאשִׁית)
puts [lindex $l 1]; # (1,1,1,2,בָּרָא)
puts [lindex $l 2]; # (1,1,1,3,אֱלֹהִים)
puts [lindex $l 3]; # (1,1,1,4,אֵת)
puts [lindex $l 4]; # (1,1,1,5,הַשּׁמַיִם)
puts [lindex $l 5]; # (1,1,1,6,וְאֵת)
puts [lindex $l 6]; # (1,1,1,7,הָאָֽרֶץ׃)

set v [join $l ,]; # (1,1,1,1,בְּרֵאשִׁית),(1,1,1,2,בָּרָא),(1,1,1,3,אֱלֹהִים),(1,1,1,4,אֵת),(1,1,1,5,הַשּׁמַיִם),(1,1,1,6,וְאֵת),(1,1,1,7,הָאָֽרֶץ׃)

set r "insert into vowel_pts (book_no, chapter_no, verse_no, index_no, word) values $v"
dbws eval $r

感谢您提供示例和建议。我仍然想了解 join 是否导致了 SQL 语句的顺序错误,但是,在查看了@Shawn 提供的 SQL 之后,我尝试使用 SQLite JSON 扩展和下面的也可以。如果去掉arr_vptable的where子句的限制,旧约三十九卷每一节的字都单独写成一行,正如@DonalFellows 所建议的那样,它在我使用了 10 年的普通笔记本电脑上只需几秒钟即可完成。再次感谢。

with
arr_vp as (
select book_no, chapter_no, verse_no,
       '["' || replace(original,' ', '","' ) || '"]' as t
from src_original
where book_no=1
  and chapter_no=1
  and verse_no < 3
  and type_no=0
)

select a.book_no, a.chapter_no, a.verse_no,
       (key+1) as index_no,
       j.value as vowel_pts
from arr_vp a,
     json_each( ( select t
                  from arr_vp r
                  where r.book_no=a.book_no
                    and r.chapter_no=a.chapter_no
                    and r.verse_no=a.verse_no ) ) as j
where j.type = 'text';

与 SQL 一样,在准备好的语句中使用参数,而不是尝试在运行时将值直接添加到查询字符串中。类似于:

# Populate an array of dicts
set l {}
set sql {select * from src_original where type_no=0 and book_no < 40 limit 1}
dbws eval $sql origLang {
    set i 0
    foreach x $origLang(original) {
        lappend l [dict create book_no $origLang(book_no) \
                               chapter_no $origLang(chapter_no) \
                               verse_no $origLang(verse_no) \
                               index_no [incr i] \
                               word $x]
    }
}

# And insert them one at a time.
foreach w $l {
    dict with w {
        dbws eval {
            INSERT INTO vowel_pts(book_no, chapter_no, verse_no, index_no, word)
            VALUES ($book_no, $chapter_no, $verse_no, $index_no, $word)
        }
    }
}

有关在 SQL 语句中嵌入(未计算的)变量名称并将值绑定到它们的更多信息,请参阅 the documentation


我确实设法想出一种方法来仅在核心 Sqlite3 中实现它,假设一个标准的 space 字符分隔单词,我认为这会起作用:

dbws eval {
    WITH verse AS (SELECT * FROM src_original WHERE type_no = 0 AND book_no < 40 LIMIT 1),
    words AS
      (SELECT book_no, chapter_no, verse_no,
              substr(original || ' ', 1, instr(original || ' ', ' ') - 1) AS word,
              substr(original || ' ', instr(original || ' ', ' ') + 1) AS original,
              1 AS index_no
       FROM verse
       UNION ALL
       SELECT book_no, chapter_no, verse_no,
              substr(original, 1, instr(original, ' ') - 1),
              substr(original, instr(original, ' ') + 1),
              index_no + 1
       FROM words WHERE length(original) > 0)
    INSERT INTO vowel_pts(book_no, chapter_no, verse_no, index_no, word)
    SELECT book_no, chapter_no, verse_no, index_no, word FROM words
}

join 命令不会改变内存中字符的顺序。然而,屏幕上从左到右和从右到左的混合脚本的渲染是......好吧,到处都是。

但是由于您这样做只是为了将数据从一个数据库移动到另一个数据库,所以找到一种不将数据本身带入 Tcl 的方法。它也会更快、更安全。