bash 使用 sed(或类似的东西)修改变量的内容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19551613/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Modify the content of variable using sed (or something similar)
提问by jgyou
I wrote a BASH file that features multiple embedded loops of the form
我写了一个 BASH 文件,其中包含多个嵌入的表单循环
for P in {'0.10','0.20', [...] '0.90','1.00'}; do
for Q in {'0.10','0.20', [...] ,'0.90','1.00'}; do
[...]
I use these variables both as parameters for a command line application, and to create file names directly in BASH. I would like to create duplicates, say $P_REP=0_10
that replaces the dot by an underscore without writting a explicit switch statement for every case, or some hardcoded equivalent. The (non-elegant way) I found to go about it is to
我将这些变量用作命令行应用程序的参数,并直接在 BASH 中创建文件名。我想创建重复项,比如$P_REP=0_10
用下划线替换点,而不用为每种情况或一些硬编码的等价物编写显式的 switch 语句。我发现的(非优雅方式)是
- dump the content of
P,Q
to a temporary file. - replace the dot by an underscore using
sed 's/./_/ -i
. - read the file again and load its content to the new variable.
- 将 的内容转储
P,Q
到临时文件。 - 使用下划线替换点
sed 's/./_/ -i
。 - 再次读取文件并将其内容加载到新变量中。
Hence, I was wondering if it is possible to run a sed like command directly on the content of a variable?
因此,我想知道是否可以直接对变量的内容运行类似 sed 的命令?
回答by John Kugelman
You can do pattern substitution directly in bash:
您可以直接在 bash 中进行模式替换:
P_REP=${P/./_}
Q_REP=${Q/./_}
From the bash(1) man page:
从 bash(1) 手册页:
Paramter Expansion
${parameter/pattern/string}
Pattern substitution.The patternis expanded to produce a pattern just as in pathname expansion. Parameteris expanded and the longest match of patternagainst its value is replaced with string. If patternbegins with
/
, all matches of patternare replaced with string. Normally only the first match is replaced. If patternbegins with#
, it must match at the beginning of the expanded value of parameter. If patternbegins with%
, it must match at the end of the expanded value of parameter. If stringis null, matches of patternare deleted and the / following patternmay be omitted. If parameter is@
or*
, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with@
or*
, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.
参数扩展
${parameter/pattern/string}
模式替换。的 图案被膨胀,以产生一个模式,就像在路径扩展。 参数被扩展,模式与其值的最长匹配被替换为string。如果模式开头
/
,所有的比赛模式被替换为的字符串。通常只替换第一个匹配项。如果模式以 开头#
,则它必须匹配参数扩展值的开头。如果模式以 开头%
,则它必须匹配参数扩展值的末尾。如果字符串为空,模式的匹配被删除并且 / 后面的模式可以被省略。如果参数是@
或*
,则对每个位置参数依次进行替换操作,展开的结果就是列表。如果参数是一个以@
or*
为下标的数组变量,则对数组中的每个成员依次进行替换操作,展开后就是结果列表。
回答by Zero Piraeus
John Kugelman's answer is fine for your example, but if you need to process the content of a variable with the actual sed program (or some other arbitrary command), you can do it like this:
John Kugelman 的回答对您的示例很好,但是如果您需要使用实际的 sed 程序(或其他一些任意命令)处理变量的内容,您可以这样做:
P_REP=$(sed 's/\./_/' <<< "$P")
回答by jwatkins
For the exact problem you are mentionning, use John's proposition above.
对于您提到的确切问题,请使用上面约翰的命题。
I would however mention, in case you ever have to do something similar that can't be solved with bash's pattern substitution syntax, that you don't need to actually create temporary files to transform content with sed or similar commands. First, you can pipe a variable directly to a program as STDIN. Second, you may get the output of a command (oeither it's STDOUT, STDERR, or both) directly into a shell variable.
但是,我要提一下,如果您不得不执行 bash 的模式替换语法无法解决的类似问题,则您无需实际创建临时文件来使用 sed 或类似命令转换内容。首先,您可以将变量作为 STDIN 直接通过管道传输到程序。其次,您可以将命令的输出(或者是 STDOUT、STDERR 或两者)直接放入 shell 变量中。
So in your example, you would have had:
所以在你的例子中,你会有:
for P in 0.10 0.20 [...] 0.90 1.00 ; do
for Q in 0.10 0.20 [...] 0.90 1.00 ; do
P_REP=$( sed 's/\./_/g' <<< "$P" )
Q_REP=$( sed 's/\./_/g' <<< "$Q" )
done
done
Note also that the array syntax (that is { '0.10', '0.20', ...}
) is mostly specific to Bash and a very few Bash-followers. When it is easy to do so, you might prefer the more classical approach to for loops in shell, as I domonstrated above. Then your code will safetly execute in all posix-compliant shells.
另请注意,数组语法(即{ '0.10', '0.20', ...}
)主要针对 Bash 和极少数 Bash 追随者。当这样做很容易时,您可能更喜欢在 shell 中使用更经典的 for 循环方法,正如我上面所演示的。然后您的代码将在所有符合 posix 的 shell 中安全执行。
回答by Alexander Vogt
For loops you could use:
对于循环,您可以使用:
#!/bin/bash
P_REP=$(for P in '0.10' '0.20' '0.90' '1.00'; do echo ${P/./_} ; done)
Q_REP=$(for Q in '0.10' '0.20' '0.90' '1.00'; do echo ${Q/./_} ; done)
echo ${P_REP[@]}
echo ${Q_REP[@]}