需要在纯shell上更改perl代码。解析文件并更改ENV

时间:2019-06-26 15:54:26

标签: bash awk sed grep

我想更改这段代码: $(perl -p -e 's/\$(\w+)/("$ENV{$1}")/eg' < file_with_html)

并且无需perl即可进行解析和更改 file_with_html:例如包含html模板

      <th class='xtr-0-0'>Version name</th>
      <td class='xtr-0-1'>$RELEASE_TAG</td>
    </tr>
    <tr class='xtr-1'>
      <th class='xtr-1-0'>Link</th>
      <td class='xtr-1-1'>$RELEASE_URL</td>...

我需要全部改变 $(\ w +)在具有相同名称的ENV上并将该“已分析”模板发送到POST请求。 我如何使用grep / sed / awk / etc做到这一点?

UPD1: 我发送带有curl的POST

全文,在Confluence中生成新页面:

newPageTemplate=$(perl -p -e 's/\$(\w+)/("$ENV{$1}")/eg' < $CONFLUENCE_PAGE_TEMPLATE)

newPageContent="{
    \"type\": \"page\",
    \"title\": \"$CONFLUENCE_PAGE_TITLE\",
    \"ancestors\": [
        {
            \"id\": \"$CONFLUENCE_PARENTPAGE_ID\"
        }
    ],
    \"space\": {
        \"key\": \"$CONFLUENCE_SPACE\"
    },
    \"body\": {
        \"storage\": {
            \"value\": \"$(echo ${newPageTemplate})\",
            \"representation\": \"storage\"
        }
    }
}"
curl --request POST \
--url $CONFLUENCE_API_URL \
--header "authorization: Basic $JIRA_TOKEN" \
--header "content-type: application/json" \
--data "$newPageContent"

2 个答案:

答案 0 :(得分:1)

原始的perl要简单得多,但可能可以用awk完成。

Perl的v1v匹配的多一点(请参阅:https://metacpan.org/pod/perlrecharclass#Word-characters),但我假设所有这些都将出现在环境变量名称中(该名称也不能以数字开头) )。

POSIX AWK

\w
  • [0-9a-zA-Z_]提取潜在的环境变量引用
  • awk ' { n = split( $0, f, /[^$0-9a-zA-Z_]+/ ) for ( i=1; i<=n; i++ ) { v = f[i] if ( v ~ /^[$][a-zA-Z_]/ ) { sub( /^[$]/, "", v ) sub( "[$]"v, ENVIRON[v] ) } } } 1 ' file_with_html 仅匹配有效的
  • 第一个split删除前导v ~ /.../
  • 第二sub用适当的转义替换$,并用值(如果有)替换变量引用
  • sub打印每一行

警告::上面的代码有一个细微的错误。在病理情况下,一行需要多次替换,并且一个值的值看起来像是对下一个替换的引用,因为替换不会同时发生,所以该行的错误部分将被更改。例如。如果$并且行包含:1,则输出将是A='$B'; B='x';而不是.. $A .. $B ..

GNU GAWK

如果使用.. x .. $B ..扩展名,则可以修复该错误。例如,使用.. $B .. x ...

gawk

答案 1 :(得分:0)

欢迎堆栈溢出。

我需要更改具有相同名称的ENV上的所有$(\ w +)。我该如何使用grep / sed / awk / etc?

首先,grepsedawk不是“纯壳”。这些是系统上安装的命令-就像perl一样。如果可以安装perl,我建议您安装它。这非常有用。如果不是,您的下一个最佳方法可能是将源文件复制到您可以 安装perl的计算机上,并按原样运行该过程,因为最终结果是发布结果回到Confluence(例如,您可以从系统外进行POST)。

但是,如果您确实不能使用perl,那么当然可以使用grepsed和{{1 }}。

第二,到目前为止,您尝试了什么?当您向我们展示到目前为止已完成的工作,有效的方法以及无效的方法时,Stack Overflow的效果最佳。这可以帮助人们根据您的确切问题并根据您当前的理解量身定制响应。

第三,这是一个可能会指导您的脚本。同样,我不知道您知道多少awk,所以这可能有点晦涩。当然,这也不是唯一的方法,而且可能不是最好的方法。我强烈建议通过在一些示例页面上运行它并在POST之前检查输出来进行测试。 bashdiff之类的工具在这里会大有帮助。然后,即使您准备好实际发布结果,也要从子集开始慢慢进行,并在打开消防水带之前验证结果。


警告:在常见情况下,以下脚本会中断

正如@jhnc在注释中指出的那样,当替换文本包含vimdiff的替换字符的字符(例如URL中的“ /”)时,sed命令将失败。有一种方法可以补偿更多的脚本逻辑,但是恕我直言,这就是疯狂。

如果无法在目标计算机上安装sed,我的建议是我上面提到的“下一个最佳方法”:将输入数据复制到您可以在其中运行的计算机上运行perl,然后运行转换并从那里运行POST回Confluence。

但也请看看@jhnc的答案,它提供了一种解决方案,可以避免我的这种弱点。

(由于上述较简单的解决方案,我在此警告而不是删除我的答案,以防万一此方法可作为希望对其进行改进的人的基础。)

谨慎使用以下方法


replace-env-params.sh

perl

捕获somehtml

#!/bin/bash

while IFS= read -r LINE; do

    MATCH=$(echo "$LINE" | grep -E '\$[a-zA-Z0-9_]+')
    if [[ ! -z "$MATCH" ]]; then
        ENVPARAM=$(echo "$LINE" | sed 's/^.*\$\([a-zA-Z0-9_]*\).*$/\1/')

        ENVVAL="$ENVPARAM"
        REPLACE="${!ENVVAL}"

        LINE=$(echo "$LINE" | sed "s/\$[a-zA-Z0-9_]*/$REPLACE/")
    fi

    echo "$LINE"

done < $1

正在测试...

      <th class='xtr-0-0'>Version name</th>
      <td class='xtr-0-1'>$RELEASE_TAG</td>
    </tr>
    <tr class='xtr-1'>
      <th class='xtr-1-0'>Link</th>
      <td class='xtr-1-1'>$RELEASE_URL</td>

因此,您可以替换:

export RELEASE_TAG=11111111
export RELEASE_URL=22222222

./replace-env-params.sh somehtml

      <th class='xtr-0-0'>Version name</th>
      <td class='xtr-0-1'>11111111</td>
    </tr>
    <tr class='xtr-1'>
      <th class='xtr-1-0'>Link</th>
      <td class='xtr-1-1'>22222222</td>

使用

newPageTemplate=$(perl -p -e 's/\$(\w+)/("$ENV{$1}")/eg' < $CONFLUENCE_PAGE_TEMPLATE)