执行包含双引号参数的命令(从外部文件读取)

时间:2018-08-23 14:13:50

标签: bash scripting double-quotes

假设我有一个 file.txt 文件,如下所示:

some words
from here
blah blah blah
that begins
this is this

to here
other content

和另一个名为* config.conf的文件,如下所示:

name1:value1
name2:value2    
expr:sed -re "s/this/that/g" -ne "/from here/,/to here/ p"
name3:value3
name4:value4

在我的 script.sh 中,我需要获取在 config.conf 中的“ expr:”之后编写的整个sed命令,并在类似如下的管道中执行该命令这个:

#!/bin/bash

pipecommand=$(cat info | grep -e "^expr:" | sed -re "s/^expr://g")
cat file.txt | $pipecommand > output.file

但我收到此错误:

sed: -e expression #1, char 1: unknown command: `"' 

我在这里阅读了许多类似的问题,解决方案使用的是这样的数组:

pipecommand=($(cat info | grep -e "^expr:" | sed -re "s/^expr://g"))
cat file.txt | ${pipecommand[@]} > output.file

不幸的是,这仅适用于不太复杂的命令,并且仅当我直接将“ sed ... blah blah blah”命令分配给变量,而不从文件中读取该变量时。

你们当中有人知道可行的解决方案吗?

P.S .:我可以同时更改 script.sh config.conf 文件。

3 个答案:

答案 0 :(得分:3)

将其解释为有关如何将Reading quoted/escaped arguments correctly from a string的建议应用于您的用例的问题:

const ReplaceInFileWebpackPlugin = require('replace-in-file-webpack-plugin');
const UglifyJsPlugin = require( 'uglifyjs-webpack-plugin' );

module.exports = {
mode: 'production',
entry: './main.js',
output: {
    path: __dirname,
    filename: './minified.js',
},
optimization: {
    minimizer: [
        new UglifyJsPlugin(
        {
            cache: false,
            parallel: false,
            uglifyOptions: {
                compress: false,
                ecma: 6,
                mangle: false,
                keep_classnames: false,
                keep_fnames: false
            },
            sourceMap: true
        })
    ]
},
plugins: [
    new ReplaceInFileWebpackPlugin([{
        dir: __dirname,
        files: ['./main.js'],
        rules: [{
            search: /my_expression/ig,
            replace: 'replacement'
        }]
    }])
]
}; 

#!/usr/bin/env bash # the sed expression here is modified to work with BSD sed, not only GNU sed pipecommand=$(sed -ne 's/^expr://p' <info) array=( ) while IFS= read -r -d ''; do array+=( "$REPLY" ) done < <(xargs printf '%s\0' <<<"$pipecommand") <file.txt "${array[@]}" > output.file 更安全,因为eval中的单词只能被当作文字参数,而不能被解析为重定向,替换,参数扩展或其他shell语法。当然,可以使用expr:的expr来启用sh -c '...'部分中的shell语法:如果您确实想对沙箱,控件或约束进行限制,则必须约束命令(数组的第一个元素)调用的命令。

答案 1 :(得分:2)

可悲的是,您需要评估。

pipecommand=$(grep "^expr:" info | cut -d: -f2-)
eval "$pipecommand" <file.txt > output.file

尝试避免评估。

答案 2 :(得分:2)

将您的配置文件转换为具有明确定义的界面的插件。在这里,您的脚本需要一个名为sed_wrapper的函数,因此您可以在“配置文件”中提供一个具有该名称的定义(此处重命名为lib.sh)。

# This is lib.sh
sed_wrapper () {
    sed -re "s/this/that/g" -ne "/from here/,/to here/ p"
}

然后,在脚本中调用命名函数。

. lib.sh

sed_wrapper < file.txt > output.file