【问题标题】:How to search and replace in ksh within a heredoc variable once already set?一旦已经设置,如何在heredoc变量中搜索和替换ksh?
【发布时间】:2017-05-12 06:14:10
【问题描述】:

我在 ksh 方面没有丰富的经验,并且我在尝试修改脚本中的多行变量时遇到了困难。基本上,我希望删除结果输出的第一部分,直到一些“CAMP”文本并保留之后的任何内容。结果将通过电子邮件发送。不过,我尝试过的方法似乎不起作用。

这是多行部分。变量是事先设置好的。我已经删除了确切的 SQL。

   $ORACLE_HOME/bin/sqlplus -s << EndOfSql > ${LOG_FILE}
   $USERPASS@$ORACLE_SID
   SQL goes here with some other SET stuff
/
   EXIT;
EndOfSql

然后最终像这样使用它来将电子邮件发送到 MAIL_ID 中的电子邮件地址:

   mailx -s "Email subject line"\
       $MAIL_ID < $LOG_FILE;

如前所述,我想要做的是删除结果中的所有内容,直到 SQL 输出中的 heredoc 结果中的一些“CAMP”文本。我已经尝试过这样的事情,但是很难理解heredoc和变量,因为那里有很多方法:

CNTNT=${LOG_FILE#*CAMP}

  mailx -s "Email subject line"\
      $MAIL_ID < $CNTNT;

您有什么建议或资源可以指点我吗?将不胜感激。

【问题讨论】:

  • 你的主题行说“heredoc 变量”是指你的heredoc 中的$USERPASS 等吗?您是否意识到,当“heredoc”文本“提交”到 sqlplus 时,它已被 shell 扩展为其指定值?一旦扩展完成,就没有实际的方法来改变这些值。此外,您对${LOG_FILE} 的使用似乎与您的文字内容不一致。你想要LOG_FILE=/path/to/logfile.txtLOG_FILE_TEXT=$(&lt; /path/to/logfile.txt 还是别的什么?如果你使用LOG_FILE_TEXT=...,那么你可以使用mailx .... &lt;&lt;&lt; "$LOG_FILE_TEXT"
  • CNTNT="${LOG_FILE_TEXT#*CAMP}"。 . . . .祝你好运。
  • 我没有看到多行变量。取而代之的是${LOG_FILE},我希望它包含一个文件的路径。最后,在你说${LOG_FILE#*CAMP} 的地方,你并没有删除文件的内容,而是从文件名中删除任何直到并包括CAMP 的文本,而不是从文件中删除。

标签: variables ksh multiline heredoc


【解决方案1】:

正如我之前的评论中提到的,您似乎正在尝试 将输出捕获到变量中,但实际上将其发送到文件中。

作为替代方案,这可能有效:

# store the entire query in a function
sql_query() {
$ORACLE_HOME/bin/sqlplus -s << EndOfSql
$USERPASS@$ORACLE_SID
SQL goes here with some other SET stuff
/
EXIT;
EndOfSql
}

# capture function output
DATA=$( sql_query )

# Discard unwanted data
echo "${DATA#*CAMP}" | 
    mailx -s "Email subject line" ${MAIL_ID:?}

【讨论】:

    【解决方案2】:

    sql 的结果存储在一个文件中。文件名由$LOGFILE 给出。
    运行 SQL 后,变量 LOGFILE 的值仍将与之前相同,例如 /home/user7347759/camp.out
    当你想使用${..#..} 构造时,你首先必须用文件的内容填充另一个变量。 解析输出后, reslt 存储在变量中。当您使用&lt; 时,shell 需要一个文件名。因此,您需要将结果存储在一个文件中。

    # Demonstrate what you tried
    filteredfile=/tmp/user7347759.tmp
    varwithlogging="$(cat "${LOG_FILE}")"
    CNTNT="${varwithlogging#*CAMP}"
    echo "${CNTNT}"> "${filteredfile}"
    mailx -s "Email subject line"\
          $MAIL_ID < "${filteredfile}"
    rm -f "${filteredfile}"
    

    当您使用进程替换时,您可以不使用filteredfile &lt;(echo "${CNTNT}") 或者你可以使用&lt;&lt;&lt; "${CNTNT}"
    您的脚本将缩短为

    # Improved demonstration of what you tried
    varwithlogging="$(cat "${LOG_FILE}")"
    CNTNT="${varwithlogging#*CAMP}"
    mailx -s "Email subject line"\
          $MAIL_ID <<< "${varwithlogging#*CAMP}"
    

    接下来您要跳到两个临时变量 varwithloggingen CNTNT。让我们尝试一下。

    mailx -s "Email subject line"\
          $MAIL_ID <<< "$(sed 's/.*CAMP//' "${LOGFILE}")"
    

    当 LOGFILE 只有一长行时,这会很好用。当您有一个多行 LOGFILE 时,它会变得更加棘手(使用 CAMP 删除该行之前的所有行,并从剩余的第一行中删除带有 *CAMP 的部分)。
    当您可以更改 SQL 脚本时,您可以选择 @Henk 建议的内容。

    【讨论】:

      猜你喜欢
      • 2017-08-23
      • 1970-01-01
      • 2015-09-06
      • 2011-06-27
      • 1970-01-01
      • 2014-10-10
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      相关资源
      最近更新 更多