簡體   English   中英

bash腳本:在特定行之間查找文件中的內容,並對內容運行命令,將舊內容替換為命令的輸出

[英]bash script: find content in file between specific lines and run command on content, replace old content with the output of command

我是腳本專家,只是在使用一些vars,ifs,grep,awk等命令制作了真正簡單的腳本之前。

問:我有數千個帶有明文的文件(電子郵件),(有時)有幾個獨立的GPG加密文本部分,如下所示:

several lines of
cleartext stuff (more specifically: email headers)

-----BEGIN PGP MESSAGE-----
RTDHNRFSGNRTDHNRFSGNRTDHNRFSGN
RTDHNRFSGNRTDHNRFSGNRTDHNRFSGN
-----END PGP MESSAGE-----

some more lines
of cleartext

-----BEGIN PGP MESSAGE-----
WPGLUFPJUWPGLUFPJUWPGLUFPJU
WPGLUFPJUWPGLUFPJUWPGLUFPJU
-----END PGP MESSAGE-----

我正在嘗試制作一個(最好是)bash腳本,該腳本遍歷文件夾中的所有文件,找到每個GPG加密文本實例,對其進行解密,然后用解密后的文本替換舊的加密文本,然后保存文件。 這樣,當腳本完成后,上述假設文件將如下所示:

several lines of
cleartext stuff (more specifically: email headers)

decrypted message #1

some more lines
of cleartext

decrypted message #2

當嘗試僅使用GPG解密文件時,GPG將跳過所有明文內容,僅輸出第一個解密的消息。

因此,我需要一個while循環之類的東西,以獨立查找所有以“ ----- BEGIN PGP MESSAGE -----”開頭並以“ ----- END PGP MESSAGE ----”結尾的實例-”,然后在其中使用GPG命令,然后將該實例替換為GPG命令的輸出。 然后繼續進行下一個加密文本實例。

到目前為止,我只有這幾行內容,但是它們顯然不能正確執行我想要的操作。 我不想在每個文件上都使用腳本。 而且我不想使用臨時文件,我想有一種更好的方法來完成所有這些工作。

#!/bin/bash

TEMPFILE="${1}.tmp"

## grep only the relevant gpg lines to decrypt.
## this will output ALL encrypted instances to $TEMPFILE
sed -n '/^-----BEGIN PGP MESSAGE/,/^-----END PGP MESSAGE/p' "$1" > "$TEMPFILE"

## decrypt. this will only give me the decrypted output
## of the first encrypted instance in $TEMPFILE.
## and I don't know how to shove this into the proper place in the original file.
gpg --batch -d --no-tty --output "${1}.dc.eml" "$TEMPFILE"

## remove $TEMPFILE
rm "$TEMPFILE"

這是我編寫的腳本語言,希望能對我想做的事情給出更好的解釋:

for all files in folder; do
    while i can find an instance of "-----BEGIN PGP" to "-----END PGP"; do
        command: gpg decrypt > $tempvar
        command: replace the instance of "-----BEGIN PGP" to "-----END PGP" with $tempvar
    end while
end for

這可能很容易實現(我希望),但是我已經在解密難題上待了好幾天了,我無法正確地知道如何做到這一點。 任何對正確方向的幫助或暗示都會對我有很大幫助。

編輯:最終代碼,感謝格倫·傑克曼!

for file in *; do
    in_pgp_section=false
    pgp_text=""

    while IFS= read -r line; do
        if [[ $line == *BEGIN\ PGP\ MESSAGE* ]]; then
            in_pgp_section=true
        fi

        if ! $in_pgp_section; then
            printf "%s" "$line"
            continue
        fi

        pgp_text+="$line"$'\n'

        if [[ $line == *END\ PGP\ MESSAGE* ]]; then
            printf "%s" "$pgp_text" | gpg --batch -d --no-tty --use-agent
            in_pgp_section=false
            pgp_text=""
        fi
    done < "$file" > "$file.decrypted"
done

未經測試

for file in *; do
    in_pgp_section=false
    pgp_text=""

    while read line; do
        if [[ $line == "-----BEGIN PGP MESSAGE-----" ]]; then
            in_pgp_section=true
        fi

        if ! $in_pgp_section; then
            echo "$line"
            continue
        fi

        pgp_text+="$line"$'\n'

        if [[ $line == "-----END PGP MESSAGE-----" ]]; then
            printf "%s" "$pgp_text" | gpg -d
            in_pgp_section=false
            pgp_text=""
        fi
    done < "$file" > "$file.decrypting"

    ln "$file" "$file.encrypted"  &&
    mv "$file.decrypting" "$file"
done

這應該解密當前目錄中所有文件的所有PGP部分,並保留帶有“ .encrypted”擴展名的原始文件。

這不是答案,而是朝着正確方向邁出的一步:

awk '/^-----BEGIN PGP MESSAGE-----$/{store=1;txt="";}
     {if(store==0){print}else{txt=txt"\n"$0}}
     /^-----END PGP MESSAGE-----$/{store=0;print tolower(txt)}' t.txt

/^-----BEGIN PGP MESSAGE-----$/{store=1;txt="";}當行匹配時,我們初始化變量txt並將標志store設置為1 / ^ --- --END PGP訊息----- $ / {store = 0; print txt}

{if(store==0){print}else{txt=txt"\\n"$0}} ,如果標志為0,則打印該行,否則,將該行存儲(附加)到txt

/^-----END PGP MESSAGE-----$/{store=0;print tolower(txt)}當行匹配時,我們取消設置標志並做一些有趣的部分(我只是用小寫字母打印...) 。 那是你的工作。 您可能需要調用system(“ gpg”)並使用一些管道。 祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM