我有一本书的 djvu 扫描版。让我们考虑两种情况:
我想对页码进行编号
0, 1, 2, ...
(使用案例:封面应为第 0 页)我想用罗马数字对一些页面进行编号,一些用阿拉伯数字进行编号,例如:(
i, ii, iii, ..., x, 1, 2, 3, ...
使用案例:书中一些介绍性页面用罗马数字编号)
可以在Linux上实现吗?
答案1
这是可能的,但如果你不得不问的话,它不太可能对你很有用。您需要一个脚本来生成set-page-title
如下命令序列:
select 1; set-page-title "Cover"
select 2; set-page-title "i"
select 3; set-page-title "ii"
select 4; set-page-title "iii"
select 5; set-page-title "1"
select 6; set-page-title "2"
select 7; set-page-title "3"
select 8; set-page-title "4"
select 9; set-page-title "5"
select 10; set-page-title "6"
...
您必须通过管道输出脚本的输出才能djvused
将更改提交到 DjVu 文件:
djvu_pagination | djvused -f - -s file.djvu
但请注意,您只有一次机会,如果数字错误,您将无法再次运行相同的命令,您必须通过引用组件名称来重置逻辑页码。事情是这样的:
select "all_24223_to_00243.cpc.djvu"; set-page-title "all_24223_to_00243.cpc.djvu"
select "all_24223_to_00243.cpc0002.djvu"; set-page-title "all_24223_to_00243.cpc0002.djvu"
select "all_24223_to_00243.cpc0003.djvu"; set-page-title "all_24223_to_00243.cpc0003.djvu"
select "all_24223_to_00243.cpc0004.djvu"; set-page-title "all_24223_to_00243.cpc0004.djvu"
select "all_24223_to_00243.cpc0005.djvu"; set-page-title "all_24223_to_00243.cpc0005.djvu"
...
然后,您可以将这些命令通过管道传递到djvused
上面:
djvu_reset_pagination | djvused -f - -s file.djvu
曾几何时,人们使用脚本来处理所有这些事情。那些日子现在已经一去不复返了。
答案2
2021 年 3 月更新:更新脚本 + 跳过页面
(改编自lcd047的答案)
创建 .djvu 文件的备份副本,以防出现问题。
numconv
从安装包这里。
将以下内容保存为文本文件,例如generate_page_list.sh
:
#!/bin/bash
## Set these parameters:
# Name first/last page $CNAME/$BCNAME? (Yes/No=0/1)
COVER=1
BCOVER=0
CNAME="C"
BCNAME="BC"
# Lowest roman page number
MINROMAN=3
# Highest roman page number
MAXROMAN=6
# Lowest arabic page number
MINARABIC=1
# Highest arabic page number
MAXARABIC=10
# Create/Empty new_page_list
> new_page_list
# Initialise total page number iTOTAL
iTOTAL=1
# Generate list of set-page-title commands
if [[ "$COVER" == 1 ]]; then
echo "select $iTOTAL; set-page-title \"$CNAME\"" >> new_page_list
((iTOTAL++))
fi
for (( i=$MINROMAN; i<=$MAXROMAN; i++)); do
iROMAN=`echo $i | numconv -f Western -t Roman_Lower`
echo "select $iTOTAL; set-page-title \"$iROMAN\"" >> new_page_list
((iTOTAL++))
done
for (( i=$MINARABIC; i<=$MAXARABIC; i++)); do
echo "select $iTOTAL; set-page-title \"$i\"" >> new_page_list
((iTOTAL++))
done
if [[ "$BCOVER" == 1 ]]; then
echo "select $iTOTAL; set-page-title \"$BCNAME\"" >> new_page_list
((iTOTAL++))
fi
使generate_page_list.sh
可执行文件通过
chmod +x generate_page_list.sh
通过运行脚本
./generate_page_list.sh
这会生成一个文件new_page_list
。在文本编辑器中打开此文件,检查它是否包含set-page-title
如下命令序列:
select 1; set-page-title "Cover"
select 2; set-page-title "i"
select 3; set-page-title "ii"
select 4; set-page-title "iii"
select 5; set-page-title "1"
select 6; set-page-title "2"
select 7; set-page-title "3"
select 8; set-page-title "4"
select 9; set-page-title "5"
select 10; set-page-title "6"
...
传递此列表以djvused
提交对 DjVu 文件的更改:
djvused -f new_page_list -s file.djvu
带有跳过页面的脚本
如果您的 .djvu 文件缺少页面(例如扫描时留下的空白页面),您可以使用上述脚本的以下扩展名:
#!/bin/bash
## Set these parameters:
# Name first/last page $CNAME/$BCNAME? (Yes/No=0/1)
COVER=1
BCOVER=0
CNAME="C"
BCNAME="BC"
# Lowest roman page number
MINROMAN=3
# Highest roman page number
MAXROMAN=6
# Skipped roman page numbers
SKIPROMAN=""
# Lowest arabic page number
MINARABIC=1
# Highest arabic page number
MAXARABIC=10
# Skipped arabic page numbers
SKIPARABIC="3 5"
# Create/Empty new_page_list
> new_page_list
# Initialise total page number iTOTAL
iTOTAL=1
# Generate list of set-page-title commands
if [[ "$COVER" == 1 ]]; then
echo "select $iTOTAL; set-page-title \"$CNAME\"" >> new_page_list
((iTOTAL++))
fi
for (( i=$MINROMAN; i<=$MAXROMAN; i++)); do
if [[ ! " $SKIPROMAN " =~ " $i " ]]; then
iROMAN=`echo $i | numconv -f Western -t Roman_Lower`
echo "select $iTOTAL; set-page-title \"$iROMAN\"" >> new_page_list
((iTOTAL++))
fi
done
for (( i=$MINARABIC; i<=$MAXARABIC; i++)); do
if [[ ! " $SKIPARABIC " =~ " $i " ]]; then
echo "select $iTOTAL; set-page-title \"$i\"" >> new_page_list
((iTOTAL++))
fi
done
if [[ "$BCOVER" == 1 ]]; then
echo "select $iTOTAL; set-page-title \"$BCNAME\"" >> new_page_list
((iTOTAL++))
fi
SKIPARABIC(或 SKIPROMAN)是一个字符串,其中包含要跳过的页码列表,以空格分隔。例如,您可以单独输入数字:
SKIPARABIC="3 4"
或作为一个范围
SKIPARABIC="{3..5}"
或一个或多个数字和范围的组合(同样用空格分隔
SKIPARABIC="{3..5} 7 {9..15}"
我正在使用字符串比较(根据这个 stackoverflow 答案),这可能不是最有效的,但它是我能找到的根据列表跳过循环中的迭代的最简单且最具可读性的解决方案。
答案3
2023 年 11 月更新:hife 的答案不依赖于numconv
这由 hife 回答此页面依赖于numconv
将阿拉伯数字转换为罗马数字的包。但是,我numconv
在 kubuntu 系统上安装时遇到了问题。也就是说,它似乎安装正常,但是当调用时,它返回错误numconv: error while loading shared libraries: libuninum.so.5: cannot open shared object file: No such file or directory
(即使库位于它应该在的位置,在 中/usr/local/lib/
)。
因此,我编写了一个执行转换的 bash 脚本,arabic_to_roman
.它基本上是所提出算法的 bash 音译这里。该脚本在本文末尾给出。
hife 脚本中唯一需要更改的是以下命令:
iROMAN=`echo $i | numconv -f Western -t Roman_Lower`
该命令应替换为
iROMAN=`arabic_to_roman $i`
为了使其工作,脚本arabic_to_roman
应该位于搜索路径中的目录中;否则,您需要提供脚本的完整路径。当然,脚本应该是可执行的(例如通过使用chmod +x arabic_to_roman
)。
最后,这是脚本arabic_to_roman
:
#!/bin/bash
# sample usage:
# arabic_to_roman 54
# returns liv
# Function to convert Arabic number to Roman numeral
convert_to_roman() {
num=$1
res=""
while [ $num -ge 1000 ]; do
res+="m"
((num-=1000))
done
while [ $num -ge 900 ]; do
res+="cm"
((num-=900))
done
while [ $num -ge 500 ]; do
res+="d"
((num-=500))
done
while [ $num -ge 400 ]; do
res+="cd"
((num-=400))
done
while [ $num -ge 100 ]; do
res+="c"
((num-=100))
done
while [ $num -ge 90 ]; do
res+="xc"
((num-=90))
done
while [ $num -ge 50 ]; do
res+="l"
((num-=50))
done
while [ $num -ge 40 ]; do
res+="xl"
((num-=40))
done
while [ $num -ge 10 ]; do
res+="x"
((num-=10))
done
while [ $num -ge 9 ]; do
res+="ix"
((num-=9))
done
while [ $num -ge 5 ]; do
res+="v"
((num-=5))
done
while [ $num -ge 4 ]; do
res+="iv"
((num-=4))
done
while [ $num -ge 1 ]; do
res+="i"
((num-=1))
done
echo "$res"
}
# Check if an argument is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <arabic_number>"
exit 1
fi
# Call the function with the provided Arabic number
convert_to_roman $1