我有一个文本文件中有多个名字,例如
John Doe Jane Doe Mike Miller ...
和一个pdf文件,其中包含与文本文件中名称一样多的页面。
如何在第一页插入/粘贴名字,在第二页插入第二个名字等等? 我必须从Linux服务器上的命令行来完成。
您可以通过使用Ghostscript在PostScript中进行编程来完成。 您需要首先查找PDF文件中的页数或文本文件中的行数,您可能希望检查这些内容是否相同。
使用Ghostscript pdfwrite设备,从PDF文件执行页面描述,然后从文本文件中读取文本。 在内容上正确定位当前点,选择适当的字体和大小,并显示文本。 然后执行showpage来渲染页面。
您可以获得一个包含所有页面的大型PDF文件,也可以获得每页一个PDF文件。
请注意,对于不熟悉PostScript编程的人来说,这不是一项任务。
这个程序适用于我,但我没有做任何伟大的测试。 我用了2个空白页面的PDF文件和2行文本的文本文件。 您将需要修改InsertText过程移动到正确的位置。 您还需要修改字体选择和大小(在程序中搜索findfont)
这是一个示例用法:
gs -sDEVICE=pdfwrite \ -sOutputFile=out.pdf \ -sPDF_File=test.pdf \ -sText_File=test.txt \ textinsert.ps
请注意,这完全是Ghostscript特有的,绝对不适用于任何其他PostScript / PDF使用者。
%!PS %% Copyright (C) Ken Sharp and Artifex Software Inc All rights reserved. %% Permission granted to use, copy, modify and redistribute provided this %% copyright remains intact. No warranty express or implied. %% %% Process a PDF file and a text file where one line of text from the text %% file is drawn onto a page of the PDF file. %% Redefine showpage so that we can draw the PDF page %% without emitting it %%s /TextInsertDict 20 dict dup 3 1 roll def begin /InsertText { %% Read a line of text from the text file TFile 256 string readline pop %% Move to the desired location and draw the text 100 100 moveto show } bind def /Textpdfshowpage{ save /PDFSave exch store /PDFdictstackcount countdictstack store /PDFexecstackcount count 2 sub store (before exec) VMDEBUG % set up color space substitution (this must be inside the page save) pdfshowpage_setcspacesub .writepdfmarks { % Copy the boxes. { /CropBox /BleedBox /TrimBox /ArtBox } { 2 copy pget { % .pdfshowpage_Install transforms the user space do same here with the boxes oforce_elems 2 { Page pdf_cached_PDF2PS_matrix transform 4 2 roll } repeat normrect_elems 4 index 5 1 roll fix_empty_rect_elems 4 array astore mark 3 1 roll /PAGE pdfmark } { pop } ifelse } forall % Copy annotations and links. dup /Annots knownoget { 0 1 2 index length 1 sub { 1 index exch oget dup type /dicttype eq { dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse } { pop } ifelse } for pop } if } if % end .writepdfmarks % Display the actual page contents. 8 dict begin /BXlevel 0 def /BMClevel 0 def /OFFlevels 0 dict def /BGDefault currentblackgeneration def /UCRDefault currentundercolorremoval def %****** DOESN'T HANDLE COLOR TRANSFER YET ****** /TRDefault currenttransfer def matrix currentmatrix 2 dict 2 index /CropBox pget { oforce_elems normrect_elems boxrect 4 array astore 1 index /ClipRect 3 -1 roll put } if dictbeginpage setmatrix /DefaultQstate qstate store count 1 sub /pdfemptycount exch store % If the page uses any transparency features, show it within % a transparency group. dup pageusestransparency dup /PDFusingtransparency exch def { % Show the page within a PDF 1.4 device filter. 0 .pushpdf14devicefilter { /DefaultQstate qstate store % device has changed -- reset DefaultQstate % If the page has a Group, enclose contents in transparency group. % (Adobe Tech Note 5407, sec 9.2) dup /Group knownoget { 1 index /CropBox pget { /CropBox exch } { 1 index get_media_box pop /MediaBox exch } ifelse oforce_elems normrect_elems fix_empty_rect_elems 4 array astore .beginformgroup showpagecontents .endtransparencygroup } { showpagecontents } ifelse } stopped { % todo: discard .poppdf14devicefilter /DefaultQstate qstate store % device has changed -- reset DefaultQstate stop } if .poppdf14devicefilter /DefaultQstate qstate store % device has changed -- reset DefaultQstate } { showpagecontents } ifelse .free_page_resources InsertText % todo: mixing drawing ops outside the device filter could cause % problems, for example with the pnga device. endpage end % scratch dict % Some PDF files don't have matching q/Q (gsave/grestore) so we need % to clean up any left over dicts from the dictstack PDFdictstackcount //false { countdictstack 2 index le { exit } if currentdict /n known not or end } loop { StreamRunAborted not { ( **** Warning: File has unbalanced q/Q operators \(too many q's\)\n) pdfformaterror } if } if pop count PDFexecstackcount sub { pop } repeat (after exec) VMDEBUG Repaired % pass Repaired state around the restore PDFSave restore /Repaired exch def } bind def %% Check both our arguments are defined leaves true on the %% stack if so, false otherwise %% {PDF_File} stopped { (No PDF_File defined\n) print false } { {Text_File} stopped { pop (No Text-File defined\n) print false } { pop pop true }ifelse }ifelse { %% First find the number of lines of text in the text file %% /TextLineCount 0 def Text_File (r) file dup { dup 256 string readline { pop /TextLineCount TextLineCount 1 add def } { pop exit } ifelse } loop closefile %% First find the number of pages in the PDF file %% PDF_File (r) file runpdfbegin pdfpagecount TextLineCount eq { runpdfend true } { runpdfend false } ifelse exch closefile %% If the number of pages is the same as the number of lines %% the we process the files, otherwise warn and exiot %% { %% Select font and size %% /Times-Roman findfont 20 scalefont setfont %% Open the text file agaiin %% /TFile Text_File (r) file def %% Open the PDF file and begin PDF processing PDF_File (r) file runpdfbegin %% For each page.... %% 1 1 TextLineCount { %% draw the content of this page %% pdfgetpage dup /Page exch store pdfshowpage_init pdfshowpage_setpage Textpdfshowpage } for %% Terminate PDF processing %% runpdfend %% Close the text file %% TFile closefile } { (Warning, Number of pages not equal to the number of text lines, aborting!\n) print flush }ifelse } { (Incorrect usage\n) print (Usage: \n) print (gs -sDEVICE=pdfwrite -o <outputfile> -sPDF-File=<PDF file> -sText_File=<Text file> textinsert.ps\n) print (NB all switches are case-sensitive\n) print } ifelse end