我收到了一个表格数据的 PDF 文件,我已将其转换为纯文本进行处理。
pdftotext -nopgbrk -layout file.pdf
这做得相当不错,但使用空格来分隔/分隔列中的字段,并且似乎主要对保留视觉布局而不是“结构”布局感兴趣,即,没有一致或可靠的分隔符。所以现在我将 2 个或更多空格转换为制表符:
sed -i 's/[[:space:]]\{2,\}/\t/g' file.txt
使用cat -vte
我看到这在文件中放置选项卡做得非常好....但是,我想请你帮忙的第二个字段有一些不一致之处。
请参阅以下比较以进行说明:
正常/预期结果:
79879 5.6 0.5 MG EN SQ TFK 世界报告 09-24-2004 儿童编辑时间,ORD1915643 79880 5.5 0.5 MG EN SQ TFK 世界报告 10-01-2004 儿童编辑时间,ORD1915643 79881 6.0 0.5 MG EN SQ TFK 世界报告 10-08-2004 儿童编辑时间,ORD1915643 79882 5.5 0.5 MG EN SQ TFK 世界报告 2004 年 10 月 22 日儿童编辑时间,ORD1915643 79883 5.9 0.5 MG EN SQ TFK 世界报告 10-29-2004 儿童编辑时间,ORD1915643
一些奇怪和不一致的地方:
72 5.2 3.0 MG EN LS Ramona 和她的父亲 Cleary,Beverly ORD2111460 491 4.8 4.0 MG EN LS Ramona 和她的母亲 Cleary,Beverly ORD1748201 134 5.6 3.0 MG EN LS Ramona Quimby,8 岁 Cleary,Beverly ORD1748201 29 4.7 5.0 MG EN LS 来自 Basil E. Konigsburg 夫人的混合文件,EL ORD1525579
请注意,“smushing”效应可能出现在字段 2 或字段 3 中......并且,字段数与“正常”结果相差 1 或 2。
...所以,为了解决这个问题,我尝试了以下方法:
awk -F'\t' 'OFS="\t";$1 ~ /^[[:digit:]]/{print $1,gensub(/[[:space:]]/,"\t","g",$2),$3,$4,$5,$6,$7}' file.txt
这似乎使每条线或至少大部分线加倍并切断了字段。
编辑 这似乎工作......到目前为止,仍在测试。
awk -F'\t' '{$2 = gensub( /[[:space:]]/, "\t", "g", $2 );
$3 = gensub( /[[:space:]]/, "\t", "g", $3 )}
{OFS="\t";print}' file.txt
有没有使用 awk 解决这个问题的简单方法?
更新
有些人要求提供一个代表我的空格选项卡转换之前的状态的样本。下图表示文档中前一个样本所在位置附近的样本。看起来差不多......除了一个[下面]是间隔的,另一个[上面]是标签。请注意 pdftotext 在下面的不同示例中处理第 2 列的方式...有时会拆分,有时会制作单个列。
样品 1:
72 5.2 3.0 MG EN RP Ramona 和她的父亲 Cleary,Beverly ORD0630871 是孤儿 491 4.8 4.0 MG EN RP Ramona 和她的母亲 Cleary,Beverly ORD0785414 也是孤儿 186 4.8 4.0 MG EN RP Ramona Forever Cleary,贝弗利 ORD0630871 永远的孤儿
样本 2:
79871 5.7 0.5 MG EN SQ TFK 世界报告 03-18-2005 儿童编辑时间,ORD1915643 79872 5.8 0.5 MG EN SQ TFK 世界报告 04-01-2005 儿童编辑时间,ORD1915643 79873 6.0 0.5 MG EN SQ TFK 世界报告 04-08-2005 儿童编辑时间,ORD1915643
更新 2
对 Ed 的提交进行了以下更改。认为它可以简化,但它的工作原理。它必须允许孤立线。
$1 ~ /^[[:digit:]]+/{
for (i=1;i<=6;i++)
printf "%s\t", $i
n = split($0,tmp,/ +/)
for (i=2;i>=0;i--)
printf "%s\t", tmp[n-i]
print ""
}
$1 ~ /^[^[:digit:]]+/ {print $0}
也许这更漂亮:
{
if ($1 ~ /^[[:digit:]]+/) {
for (i=1;i<=6;i++)
printf "%s\t", $i
n = split($0,tmp,/ +/)
for (i=2;i>=0;i--)
printf "%s\t", tmp[n-i]
print ""
}
else print $0;
}