Thay đổi 2 hoặc nhiều tài liệu LibreScript để có cùng kiểu dáng / định dạng


14

Giả sử tôi có một thư mục chứa khoảng 100 .rtftệp tôi chỉnh sửa với LibreOffice Writer.

Tôi mong muốn rằng tất cả các tệp trong thư mục đó sẽ có cùng chỉ thị kiểu văn bản phong phú cơ bản chính xác:

* font-family: Ubuntu             # All text in all files is now Ubuntu;
* font-size: 12px                 # All text in all files is now 12px big;
h1: 28px                          # All h1's are now 28px big;
if font-size: 18px {make it 22px} # All text with font-size 18px is now 22px;

Và cứ thế ... Vì vậy, về cơ bản, tôi muốn thay đổi tất cả các tệp cùng một lúc. Là "kiểu dáng số lượng lớn" có thể?

Có lẽ điều đó là có thể với CLI bằng cách nào đó?


3
Đây không phải là một nhiệm vụ dễ dàng tôi nghĩ. Nếu tất cả chúng đều được cấu trúc theo cùng một cách, có lẽ bạn có thể sử dụng một số giải pháp hacky bằng cách thay thế văn bản trong các tệp .rtf từ dòng lệnh. Tuy nhiên, điều này phụ thuộc rất nhiều vào cách các tệp rtf trông như thế nào và chúng giống nhau như thế nào.
Sebastian Stark

Tôi đã tìm thấy trợ giúp trong Stack Overflow cho một macro LibreOffice Writer hoàn toàn mới bắt đầu từ đầu tối nay. Chúng tôi không còn cần phải biết mọi kích thước phông chữ hiện có.
WinEunuuchs2Unix

Trong nỗ lực cuối cùng, tôi đã yêu cầu các chuyên gia Stack Overflow đăng câu trả lời tại đây trước khi thời gian gia hạn kết thúc: stackoverflow.com/questions/49640951/
Thẻ

Các bạn có hàng chục ngàn điểm danh tiếng. Tôi khiêm tốn đề nghị bạn xem xét đưa ra một cái gì đó như 500-750. Chỉ là một sự cân nhắc. Chỉ là vừa thôi.
JohnDoea

Câu trả lời:


5

Sử dụng các công cụ Libreoffice thay vì CLI

Khi tất cả những gì bạn có là các công cụ dòng lệnh, mọi thứ trông giống như một vấn đề dòng lệnh. Tôi đã quyết định viết câu trả lời này bằng cách sử dụng macro LibreScript:

  1. Sử dụng vòng lặp dòng lệnh để xử lý mọi tài liệu Nhà văn trong môi trường "không đầu".
  2. Chạy macro để thay đổi .rtftập tin tài liệu Nhà văn (Định dạng văn bản có định dạng).
  3. Macro lưu tập tin và thoát
  4. Lặp lại thành 1.

Tạo dữ liệu thử nghiệm

Tạo hai hoặc nhiều tệp chứa:

richtext2.png

Tạo tập lệnh ~/Downloads/copy-rtf.shchứa:

cp ~/Documents/*.rtf ~/Downloads

Đánh dấu là thực thi bằng cách sử dụng

chmod a+x ~/Downloads/copy-rtf.sh
  • Trong quá trình phát triển và thử nghiệm, các *.rtftệp sửa đổi macro sẽ chạy với ~/Downloadsthư mục.
  • Trước mỗi loại thử nghiệm cd ~/Downloadsvà chạy./copy-rtf.sh
  • Sau khi đầu ra hoàn hảo, chúng được sao chép trở lại vào thư mục trực tiếp.

Thư mục Tải xuống được sử dụng vì:

  • mọi người đều có một ~/Downloads
  • nó được thêm vào thường xuyên và thủ công làm trống theo định kỳ
  • nó là vĩnh viễn hơn /tmp/thư mục có thể không tồn tại trên các lần khởi động lại.

Chạy macro trong môi trường không đầu

Sử dụng câu trả lời Stack Exchange này gọi Libreoffice Writer từ dòng lệnh và truyền cho nó một tên macro toàn cầu để thực thi:

soffice -headless -invisible "vnd.sun.star.script:Standard.Module1.MySubroutine? language=Basic&location=application"

Câu trả lời trên có thể không hoạt động để có thể thử phương pháp khác :

soffice "macro:///Standard.SaveCSV.Main" $1

Cài đặt môi trường chạy thi hành Java

Để chạy macro, bạn cần cài đặt Môi trường chạy thi hành Java (JRE). Trang web của nhà phát triển có hướng dẫn tải xuống và cài đặt thủ công.

Tuy nhiên, Hỏi & Đáp AU này: https://askubfox.com/a/728153/307523 cho thấy nó đơn giản như:

sudo apt-add-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer oracle-java8-set-default

Tôi đã thử phương pháp Hỏi & Đáp của AU và sau bước đầu tiên thêm PPA, màn hình giật gân xuất hiện với thông tin bổ sung. Hữu ích nhất là liên kết để thiết lập JRE 8 trên các hệ thống Debian .

Bước thứ ba của việc cài đặt JRE 8 yêu cầu bạn sử dụng TabEnterchấp nhận Thỏa thuận cấp phép. Máy của bạn sẽ tạm dừng trong vài phút trong phần nặng nhất của quy trình cài đặt.

Bây giờ hãy mở LibreScript và chọn Công cụ -> Tùy chọn -> LibreOffice -> Nâng cao và thiết lập màn hình này:

LO JRE8 Advanced Setup.png

Nhấp vào các tùy chọn cho:

  • Sử dụng môi trường thời gian chạy Java
  • Tập đoàn Oracle 1.8.0_161
  • Cho phép ghi macro (thử nghiệm)
  • Nhấn vào OK
  • Bạn sẽ được yêu cầu khởi động lại, nhấp vào "Khởi động lại ngay".

Trình biên dịch LibreScript

Macro sẽ đọc qua toàn bộ tài liệu và:

  • đổi tên phông chữ thành Ubuntu.
  • Nếu nhóm 1 đặt kích thước phông chữ thành 28
  • khác nếu kích thước phông chữ là 18 được đặt thành 22
  • khác đặt kích thước phông chữ thành 12

Macro sẽ lưu tài liệu và thoát khỏi Libreoffice Writer.

Tắt hộp thoại

Thực hiện lưu tệp và hộp thoại này xuất hiện:

Nhà văn LO tắt RTF hộp thoại.png

Tắt thông báo này như hiển thị trên màn hình. Macro có thể không chạy đúng nếu tùy chọn này được bật.

Nội dung vĩ mô

Tôi đã mất vài ngày để ghi lại một macro bằng cách sử dụng "Công cụ" -> "Macro" -> "Ghi macro" -> "Cơ bản". Lúc đầu, nó có vẻ đầy hứa hẹn nhưng macro được ghi lại có hành vi không nhất quán và phải bị bỏ rơi cho một macro viết tay cơ bản. Một trợ giúp tìm thấy trong Stack Overflow cho một chuyên gia ở đó để giúp tôi với mã hóa cơ bản cơ bản . Đây là kết quả:

Sub ChangeAllFonts
    rem - Change all font names to Ubuntu.
    rem - If heading 1 set font size to 28
    rem - else if font size is 18 set to 22
    rem - else set font size to 12
    rem - The macro will save document and exit LibreOffice Writer.
    Dim oDoc As Object
    Dim oParEnum As Object, oPar As Object, oSecEnum As Object, oSec As Object
    Dim oFamilies As Object, oParaStyles As Object, oStyle As Object
    oDoc = ThisComponent
    oParEnum = oDoc.Text.createEnumeration()
    Do While oParEnum.hasMoreElements()
      oPar = oParEnum.nextElement()
      If oPar.supportsService("com.sun.star.text.Paragraph") Then
        oSecEnum = oPar.createEnumeration()
        Do While oSecEnum.hasMoreElements()
          oSec = oSecEnum.nextElement()
          If oSec.TextPortionType = "Text" Then
            If oSec.ParaStyleName = "Heading 1" Then
                rem ignore for now
            ElseIf oSec.CharHeight = 18 Then
                oSec.CharHeight = 22.0
            Else
                oSec.CharHeight = 12.0
            End If
          End If
        Loop
      End If
    Loop
    oFamilies = oDoc.getStyleFamilies()
    oParaStyles = oFamilies.getByName("ParagraphStyles")
    oStyle = oParaStyles.getByName("Heading 1")
    oStyle.setPropertyValue("CharHeight", 28.0)
    FileSave
    StarDesktop.terminate()
End Sub

rem Above subroutine is missing call to UbuntuFontName ()
rem also it is calling oStyle.setPropertyValue("CharHeight", 28.0)
rem which may cause problems. Will test. Also StarDesktop.terminate ()
rem is known to cause problems and will likely be reworked with a
rem a dialog box telling operator the program is finished and maybe
rem to press <Alt>+<F4>.

rem ========= Original code below for possible recycling ===========

Sub AllFonts
rem - change all font names to Ubuntu.
rem - If heading 1 set font size to 28
rem - else if font size is 18 set to 22
rem - else set font size to 12

rem The macro will save document and exit Libreoffice Writer.

Dim CharHeight As Long, oSel as Object, oTC as Object
Dim CharStyleName As String
Dim oParEnum as Object, oPar as Object, oSecEnum as Object, oSec as Object
Dim oVC as Object, oText As Object
Dim oParSection        'Current Section

oText = ThisComponent.Text
oSel = ThisComponent.CurrentSelection.getByIndex(0) 'get the current selection
oTC = oText.createTextCursorByRange(oSel)           ' and span it with a cursor

rem Scan the cursor range for chunks of given text size.
rem (Doesn't work - affects the whole document)

oParEnum = oTC.Text.createEnumeration()
Do While oParEnum.hasMoreElements()
  oPar = oParEnum.nextElement()
  If oPar.supportsService("com.sun.star.text.Paragraph") Then
    oSecEnum = oPar.createEnumeration()
    oParSection = oSecEnum.nextElement()
    Do While oSecEnum.hasMoreElements()
      oSec = oSecEnum.nextElement()
      If oSec.TextPortionType = "Text" Then
        CharStyleName = oParSection.CharStyleName
        CharHeight = oSec.CharHeight
        if CharStyleName = "Heading 1" Then
            oSec.CharHeight = 28
        elseif CharHeight = 18 Then
            oSec.CharHeight = 22
        else
            oSec.CharHeight = 12
        End If
      End If
    Loop
  End If

Loop

FileSave
stardesktop.terminate()

End Sub


Sub UbuntuFontName
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------- Select all text ------------------------------------------
dispatcher.executeDispatch(document, ".uno:SelectAll", "", 0, Array())

rem ----------- Change all fonts to Ubuntu -------------------------------
dim args5(4) as new com.sun.star.beans.PropertyValue
args5(0).Name = "CharFontName.StyleName"
args5(0).Value = ""
args5(1).Name = "CharFontName.Pitch"
args5(1).Value = 2
args5(2).Name = "CharFontName.CharSet"
args5(2).Value = -1
args5(3).Name = "CharFontName.Family"
args5(3).Value = 0
args5(4).Name = "CharFontName.FamilyName"
args5(4).Value = "Ubuntu"

dispatcher.executeDispatch(document, ".uno:CharFontName", "", 0, args5())

end sub


sub FileSave
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:Save", "", 0, Array())

end sub

2

Đây là một cách tiếp cận sử dụng Libre Office. Nó không phải là lô, nhưng nó có thể giúp truyền cảm hứng cho các câu trả lời khác.

Mở tệp rtf có phông chữ Ubuntu, H1 ở 28 pt, một số văn bản ở mức 12pt và một số ở mức 18 pt.

Đây là một ví dụ:

kiểm tra rtf

Các bước sau đây sẽ áp dụng thay đổi được yêu cầu trong câu hỏi của bạn "if font-size: 18px {make it 22px} # Tất cả văn bản có cỡ chữ 18px bây giờ là 22px;"

Nhấp vào Chỉnh sửa → Tìm & Thay thế trên menu hoặc nhấn CtrlHTùy chọn khác Nhấp vào hộp Tìm kiếm rồi nút thuộc tính Hộp kiểm Kích thước phông chữ sau đó nút Định dạng chọn 18 pt từ hộp cuộn ở bên phải Nhấp vào Thay thế bằng hộp sau đó Định dạng nút và chọn 22 pt từ hộp cuộn ở bên phải

Tìm nơi

Nhấp vào Thay thế tất cả

dòng áp dụng đã thay đổi là:

\ par \ pard \ plain \ S \ {\ rtlch \ ltrch \ loch \ fs36 \ loch \ f6

fs36 đổi thành fs44

trường khác chỉ thay đổi là trường thời gian quay lại mà bạn có thể muốn hoặc không muốn cập nhật:

{\ revtim \ yr2018 \ mo3 \ dy31 \ hr22 \ min19}

Biết những gì thay đổi cung cấp cho chúng tôi một mô hình để phát triển một cách tiếp cận hàng loạt. Có thể ghi lại một Macro thực hiện điều này khi mở tài liệu hoặc phát triển tập lệnh thực hiện các thay đổi theo ý muốn.


1

Có một số manh mối tuyệt vời về cách người ta có thể nói về điều này trong đặc tả RTF.

Đây là phân tích của tôi về vấn đề này.

Hoàn thành việc này bằng CLI khi bạn phỏng đoán dường như là cách tiếp cận đơn giản nhất vì tôi chưa thấy bất kỳ ứng dụng dựa trên GUI nào có thể xử lý loại chuyển đổi hàng loạt này. Dường như bạn chỉ cần sửa đổi tiêu đề:

Tiêu đề có cú pháp sau:

<header>
    \rtf <charset> \deff? <fonttbl> <filetbl>? <colortbl>? <stylesheet>? <listtables>? <revtbl>?

Each of the various header tables should appear, if they exist, in the above order. Document properties can occur before and between the header tables. A property must be defined before being referenced. Specifically:

* The style sheet must occur before any style usage.

* The font table must precede any reference to a font.

* The \deff keyword must precede any text without an explicit reference to a font, because it specifies the font to use in such cases.

Cá nhân, khi xem xét thông tin này, tôi nhận thấy rằng mọi thứ bạn đang cố gắng thực hiện có vẻ như được hỗ trợ trong tiêu đề, từ lựa chọn phông chữ cho đến kiểu.

Có các công cụ có sẵn để giúp bạn trong quá trình này mà tôi sẽ phác thảo bên dưới vì tôi không có ví dụ về kiểu tài liệu bạn có cũng như kiểu tài liệu bạn muốn và một câu trả lời chung chung hơn có thể sẽ được sử dụng nhiều hơn cho cộng đồng một mục tiêu cho tình huống chính xác của bạn.

grepsẽ hữu ích để phân tích các tệp hiện có sẽ được chuyển đổi và một mẫu của kiểu đích cho các lựa chọn hiện có <fonttbl>
<stylesheet>. Khi đã xác định những gì bạn thực sự có, bạn sẽ có thể viết một tập lệnh đơn giản sử dụng sedđể thay thế nội dung tiêu đề hiện có bằng nội dung tiêu đề mong muốn. Có rất nhiều ví dụ về cách lặp qua các tệp trong tập lệnh bash ( ví dụ ) và cách sử dụng sed ( ví dụ ) có sẵn miễn phí nếu bạn không quen với các khái niệm này.

Ngoài ra còn có một tùy chọn dòng để thay thế một chuỗi trong một tệp. Một số có thể hoạt động tốt hơn so với những người khác tùy thuộc vào trường hợp sử dụng của bạn. Tùy thuộc vào nội dung của các tệp của bạn, có thể có hoặc không có ý nghĩa để thay thế đơn giản mọi trường hợp fs36bằng fs44shell nào bạn đang sử dụng cũng có thể dựa vào cách tốt nhất để viết biểu thức của bạn. Tùy thuộc vào độ phức tạp và nội dung của tài liệu của bạn, bạn có thể sử dụng tốt hơn sed, perlhoặc grepthậm chí là kết hợp chúng. Vì đây đã trở thành một câu hỏi lập trình, tốt nhất bạn nên giới thiệu cho bạn /programming/15402770/how-to-grep-and-replace nơi bạn sẽ dễ dàng tìm thấy 1/2 tá cách tiếp cận khác nhau, một trong những cách tiếp cận khác nhau có khả năng phù hợp với nhu cầu của bạn một cách hoàn hảo.

Ví dụ: nếu bạn muốn áp dụng các thay đổi này trên toàn hệ thống,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;như được cung cấp bởi rezizter Có khả năng là tốt nhất.

Nếu bạn muốn chứa các thay đổi của mình vào một thư mục,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'như được cung cấp bởi billtian là một lựa chọn tuyệt vời.

Để an toàn, bạn nên xử lý trước các tệp để đảm bảo rằng mọi thay đổi bạn có thể thực hiện sẽ không gây ra hậu quả ngoài ý muốn. Ví dụ:

<!-- language: lang-bash -->

    #!/bin/bash
    for f in *.rtf 
        do
        echo $f
        grep fs36
        done

Ở trên sẽ hiển thị các dòng chứa chuỗi tìm kiếm fs36 cho mỗi tệp .rtf trong thư mục.

Biên tập:

Các đặc điểm kỹ thuật gần đây nhất có thể được lấy ở đây. Tôi không thấy bất kỳ thay đổi nào sẽ ảnh hưởng đến phương pháp này.


1
Xin chào, tôi cảm ơn bạn trước tiên đã mô tả một giải pháp CLI. Vui lòng chia sẻ một ví dụ mã về cách bạn sẽ thay đổi rtfmột tiêu đề và văn bản sedđể câu trả lời sẽ tập trung vào sed.
JohnDoea

@JohnDoea Luôn sẵn sàng giúp đỡ. Tôi hy vọng cả bạn và người dùng trong tương lai đều thấy hữu ích.
Elder Geek
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.