如何从shell脚本中的命令输出grep一个字符串模式?

时间:2016-11-19 11:58:04

标签: linux bash shell ghostscript

我正在使用ghostscript压缩我的pdf文件,这会在我必须处理的密码保护的情况下抛出错误。

外壳脚本

GS_RES=`gs -sDEVICE=pdfwrite -sOutputFile=$gsoutputfile -dNOPAUSE -dBATCH $2 2>&1`

if [ "$GS_RES" != "" ]
then
    gspassmsg="This file requires a password for access"
    echo "Error message is :::::: "$GS_RES
    gspassworddoc=`awk -v a="$GS_RES" -v b="$gspassmsg" 'BEGIN{print index(a,b)}'`
    if [ $gspassworddoc -ne 0 ]
    then
        exit 3 #error code - password protected pdf
    fi
fi

执行命令后我的GS_RES值类似于以下

错误消息1:

GPL Ghostscript 9.19 (2016-03-23) Copyright (C) 2016 Artifex Software, Inc. All 
rights reserved. This software comes with NO WARRANTY: see the file PUBLIC for d
etails. Error: /syntaxerror in -file- Operand stack: Execution stack: %interp_ex
it .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --n
ostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1967 1 3 %opa
rray_pop 1966 1 3 %oparray_pop 1950 1 3 %oparray_pop 1836 1 3 %oparray_pop --nos
tringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringva
l-- 2 %stopped_push Dictionary stack: --dict:1196/1684(ro)(G)-- --dict:0/20(G)--
 --dict:78/200(L)-- Current allocation mode is local Current file position is 1

错误消息2:

GPL Ghostscript 9.19 (2016-03-23) Copyright (C) 2016 Artifex Software, Inc. All rights reserved. This software comes with NO WARRANTY: see the file PUBLIC for details. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html Error: Cannot find a 'startxref' anywhere in the file. Output may be incorrect. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html Error: An error occurred while reading an XREF table. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html The file has been damaged. This may have been caused gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html by a problem while converting or transfering the file. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html Ghostscript will attempt to recover the data. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html However, the output may be incorrect. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html Error: Trailer dictionary not found. Output may be incorrect. No pages will be processed (FirstPage > LastPage). gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html This file had errors that were repaired or ignored. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html Please notify the author of the software that produced this gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html file that it does not conform to Adobe's published PDF gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html specification. gs.pdf gsempty.pdf new_sathishks_protected.html sathishks_protected.html The rendered output from this file may be incorrect.

在错误消息2上运行awk

gspassmsg="This file requires a password for access"
gspassworddoc=`awk -v a="$GS_RES" -v b="$gspassmsg" 'BEGIN{print index(a,b)}'`

它引发了以下错误

错误:awk: newline in string GPL Ghostscript 9.19... at source line 1

错误消息3

   **** Error: Cannot find a 'startxref' anywhere in the file.
   **** Warning:  An error occurred while reading an XREF table.
   **** The file has been damaged.  This may have been caused
   **** by a problem while converting or transfering the file.
   **** Ghostscript will attempt to recover the data.
   **** Error:  Trailer is not found.

   **** This file had errors that were repaired or ignored.
   **** Please notify the author of the software that produced this
   **** file that it does not conform to Adobe's published PDF
   **** specification.

我无法使用以下答案中的代码段捕获此错误

if ! gs_res=$(gs -sDEVICE=pdfwrite -sOutputFile="$gsoutputfile" -dNOPAUSE -dBATCH "$2" 2>&1 1>/dev/null); then
  echo "Error message is :::::: $gs_res" >&2
  gspassmsg='This file requires a password for access'
  [[ $gs_res == *"$gspassmsg"* ]] && exit 3 # password protected pdf
  echo "Some other error !"
fi

请澄清以下内容

  1. 为什么awk在这里表现得很奇怪?我缺少什么?
  2. 如何在包含特殊字符的字符串中使用grep?
  3. Ghostscript是否有任何预定义的错误消息?如果可能的话,请建议一些文件来参考..
  4. 是否可以使用ghostscript压缩受密码保护的pdf?
  5. 在上述情况下,如何确保gs压缩成功?因为我可能不知道Ghostscript可能抛出的不同可能的错误,所以我可以用我执行的命令结果进行交叉检查。
  6. 我对这个shell脚本很新。有人请帮帮我。

    PS:我已经用其他细节编辑了我的问题。请仔细研究一下。如果必须添加某些内容,我会添加它。

2 个答案:

答案 0 :(得分:2)

Ghostscript的错误消息都遵循相同的模式,但是有一些问题:

输出的一部分是错误发生时操作数堆栈的转储。由于PostScript是一种编程语言,因此堆栈的内容取决于程序,并且完全不可预测。即使您正在处理PDF文件而不是PostScript程序,解释器本身也是用PostScript编写的,因此仍然适用。

  

'错误:/ syntaxerror ...'

仅限于少数实际可能的错误,PostScript语言参考手册定义了它们。

PostScript(但不是PDF)程序可以安装错误处理程序,它可以完全改变错误输出,甚至可以完全吞下错误。

关于压缩PDF文件',这绝对是你在做什么。请阅读here,其中说明了实际发生的情况。简而言之,您正在生成一个新的PDF文件,而不是压缩旧文件。

当然,只要您知道密码,就可以使用Ghostscript处理受密码保护的PDF文件。在文档here

中查找PDFPassword

现在,由于文件被加密(受密码保护),上面引用的错误消息,还有其他问题。实际上,考虑到您使用的简单命令行,我会说它有一些非常严重的错误。当然,如果没有看到文件,我无法确定。

现在,如果文件已加密,Ghostscript的输出应为:

  

GPL Ghostscript GIT PRERELEASE 9.21(2016-09-14)   版权所有(C)2016 Artifex Software,Inc。保留所有权利。   本软件不附带任何担保:有关详细信息,请参阅PUBLIC文件。

     

****此文件需要密码才能访问。

     

错误:/ pdf_process_Encrypt中的/ invalidfileaccess

     

操作数堆栈:

     

执行堆栈:%interp_exit .runexec2 --nostringval--
  --nostringval-- --nostringval-    - 2%stopped_push --nostringval---nostringval-- --nostringval-- fa lse 1%stopped_push 1983 1 3%oparray_pop 1982 1 3%oparray_ pop 1966 1 3
  %oparray_pop --nostringval-- --nostringval-- --nostri ngval--
  --nostringval-- false 1%stopped_push字典堆栈: - dict:1199/1684(ro)(G) - --dict:1/20(G) - --dict:83/200(L) - - --dict:83/200(L) - --dict:135/256(ro)(G) - --dict:291/300(ro)(G) - --dict:26/32 (L) -    - 当前分配模式是本地GPL Ghostscript GIT PRERELEASE 9.21:不可恢复的错误,退出代码1

所以只需要点击"这个文件需要密码"应该足以识别加密文件。

现在,正如mklement0所指出的,如果您想解释导致问题的实际脚本是什么,也许我们也可以帮助解决这个问题。您还没有显示脚本的输出,或者解释了无法正常工作的内容。

答案 1 :(得分:2)

KenS's helpful answer解决了有关Ghostscript本身的问题 这是一个应该有效的代码的简化版本:

# Run `gs` and capture its stderr output.
gs_res=$(gs -sDEVICE=pdfwrite -sOutputFile="$gsoutputfile" -dNOPAUSE -dBATCH "$2" 2>&1 1>/dev/null)
ec=$? # Save gs's exit code.

# Assume that something went wrong, IF:
#   - gs reported a nonzero exit code
#   - but *also* if any stderr output was produced, as
#     not all problems may be reflected in a nonzero exit code.
if [[ $ec -ne 0 || -n $gs_res ]]; then
  echo "Error message is :::::: $gs_res" >&2
  gspassmsg='This file requires a password for access'
  [[ $gs_res == *"$gspassmsg"* ]] && exit 3 # password protected pdf
fi
  • 我在gs command中引用了变量和参数引用。

  • 我已将您的重定向从2>&1更改为2>&1 1>/dev/null,以便捕获stderr输出。

    • 2>&1将stderr(2)重定向到(仍然是原始的)stdout(1),以便将错误消息发送到stdout并作为命令的一部分捕获替代($(...)); 1>/dev/null然后将stdout重定向到空设备,有效地消除所有stdout输出。请注意,早期将stderr重定向到原始标准输出受此影响,因此实际上整体命令发送到stdout的是原始的stderr输出。
      如果您想了解更多信息,请参阅我的this answer
  • 我使用的是更现代,更灵活的$(..)命令替换语法,而不是旧版`...`表单(有关背景信息,请参阅here)。

  • 我已将GS_RES重命名为gs_res,因为最好不要使用全大写的shell变量名称来avoid conflicts with environment variables and special shell variables

    < / LI>
  • 我正在使用简单模式匹配在gs的stderr输出中找到所需的子字符串。鉴于您已经在变量中测试了输入,Bash自己的字符串匹配功能将会执行(实际上变化很大),并且不需要使用外部实用程序,例如awk

至于为什么awk命令失败

听起来好像你正在使用 BSD awk,例如10.12之后macOS附带的那个(你的问题标记为linux):< / p>

BSD awk不支持通过-v传递的变量值中的换行符,除非您\ - 转义换行符。
使用未转义的多行字符串时,awk调用会在调用index()之前从根本上失败。

相比之下,GNU Awk和Mawk确实支持通过-v传递的多行字符串。

继续阅读可选背景信息

要确定您正在使用的awk实施,请运行awk --version并检查输出:

  • awk version 20070501 - &gt; BSD Awk

  • GNU Awk 4.1.3, API: 1.1 ... - &gt; GNU Awk

  • mawk: not an option: --version - &gt; Mawk

这是一个尝试使用Awk版本的简单测试:

awk -v a=$'1\n2' -v b=2 'BEGIN { print index(a, b) }'
按照预期,

Gnu Awk和Mawk输出3,而BSD Awk以awk: newline in string 1失败。

另请注意 \ - 转义换行仅适用于BSD Awk (例如,
awk -v var=$'1\\\n2' 'BEGIN { print var }'),遗憾的是,没有可移植的方式将多行变量值传递给Awk