简体   繁体   English

bash脚本:在特定行之间查找文件中的内容,并对内容运行命令,将旧内容替换为命令的输出

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

I'm a real newb at scripting, only made real simple scripts before with some vars, ifs, simple grep, awk and so on commands. 我是脚本专家,只是在使用一些vars,ifs,grep,awk等命令制作了真正简单的脚本之前。

Q: I have a few thousand files (emails) with cleartext and (sometimes) several independent sections of GPG encrypted text, something like this: 问:我有数千个带有明文的文件(电子邮件),(有时)有几个独立的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-----

I'm trying to make a (preferably) bash script that goes through all files in a folder, find each instance of GPG encrypted text, decrypt it, and replace the old encrypted text with the decrypted text, then save the file. 我正在尝试制作一个(最好是)bash脚本,该脚本遍历文件夹中的所有文件,找到每个GPG加密文本实例,对其进行解密,然后用解密后的文本替换旧的加密文本,然后保存文件。 So that when the script is done the above hypothetical file looks like this: 这样,当脚本完成后,上述假设文件将如下所示:

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

decrypted message #1

some more lines
of cleartext

decrypted message #2

When trying to just use GPG to decrypt the files GPG will skip all the cleartext stuff and just output the first decrypted message. 当尝试仅使用GPG解密文件时,GPG将跳过所有明文内容,仅输出第一个解密的消息。

So I need something like a while loop I think, to independently find all instances that start with "-----BEGIN PGP MESSAGE-----" and end with "-----END PGP MESSAGE-----" and use the GPG command on that, then replace that instance with the output of the GPG command. 因此,我需要一个while循环之类的东西,以独立查找所有以“ ----- BEGIN PGP MESSAGE -----”开头并以“ ----- END PGP MESSAGE ----”结尾的实例-”,然后在其中使用GPG命令,然后将该实例替换为GPG命令的输出。 And then continue to the next instance of encrypted text. 然后继续进行下一个加密文本实例。

So far I just have these few lines, but they obviously don't properly do what I want. 到目前为止,我只有这几行内容,但是它们显然不能正确执行我想要的操作。 I don't want to have to use the script on each individual file. 我不想在每个文件上都使用脚本。 And I don't want to use a temp file, I guess there's a much better way to do all of this. 而且我不想使用临时文件,我想有一种更好的方法来完成所有这些工作。

#!/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"

Here is my made up scripting language hopefully showing a better explanation of what I want to do: 这是我编写的脚本语言,希望能对我想做的事情给出更好的解释:

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

This is probably pretty simple to achieve (I hope) but I've been at this decryption dilemma for days now and I can't properly figure out how to do it. 这可能很容易实现(我希望),但是我已经在解密难题上待了好几天了,我无法正确地知道如何做到这一点。 Any help or hints towards the right direction will be of great help to me. 任何对正确方向的帮助或暗示都会对我有很大帮助。

EDIT: final code, thanks to glenn jackman! 编辑:最终代码,感谢格伦·杰克曼! :

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

untested 未经测试

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

This should decrypt all the PGP section for all the files in the current directory, and leave the original file with a ".encrypted" extension 这应该解密当前目录中所有文件的所有PGP部分,并保留带有“ .encrypted”扩展名的原始文件。

this is not the answer, but a step in the right direction: 这不是答案,而是朝着正确方向迈出的一步:

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="";} when the line matches, we initialise the variable txt and set the flag store to 1/^-----END PGP MESSAGE-----$/{store=0;print 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}} for each line, if the flag is 0, we print the line otherwise, we store (append) the line in txt {if(store==0){print}else{txt=txt"\\n"$0}} ,如果标志为0,则打印该行,否则,将该行存储(附加)到txt

/^-----END PGP MESSAGE-----$/{store=0;print tolower(txt)} when the line matches, we unset the flag and do the interesting part (I just print in lowercase…). /^-----END PGP MESSAGE-----$/{store=0;print tolower(txt)}当行匹配时,我们取消设置标志并做一些有趣的部分(我只是用小写字母打印...) 。 That is your job now. 那是你的工作。 You will probably need to call system("gpg") and use some pipes. 您可能需要调用system(“ gpg”)并使用一些管道。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM