8

我写了一个 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
    [...] 

我将这些变量用作命令行应用程序的参数,并直接在 BASH 中创建文件名。我想创建重复项,比如说$P_REP=0_10用下划线替换点而不为每种情况编写显式 switch 语句,或者一些硬编码的等效项。我发现的(非优雅方式)是

  1. 将内容转储P,Q到临时文件。
  2. 使用下划线替换点sed 's/./_/ -i
  3. 再次读取文件并将其内容加载到新变量中。

因此,我想知道是否可以直接在变量的内容上运行类似 sed 的命令?

4

5 回答 5

20

您可以直接在 bash 中进行模式替换:

P_REP=${P/./_}
Q_REP=${Q/./_}

从 bash(1) 手册页:

参数扩展

${parameter/pattern/string}

模式替换。模式被扩展以产生一个模式,就像在路径名扩展中一样。 参数被扩展,模式与其值的最长匹配被替换为字符串。如果pattern以 开头, pattern/的所有匹配都将替换为string。通常只替换第一场比赛。如果模式以 开头,它必须匹配参数扩展值的开头。如果模式以 开头,则它必须匹配参数扩展值的末尾。如果字符串#%为空,模式的匹配被删除并且 / 后面的模式可以被省略。如果 parameter 是@or *,则依次对每个位置参数应用替换操作,展开是结果列表。@如果 parameter 是一个以or为下标的数组变量*,则替换操作依次应用于数组的每个成员,展开是结果列表。

于 2013-10-23T20:30:22.673 回答
13

John Kugelman 的回答对您的示例来说很好,但如果您需要使用实际的 sed 程序(或其他任意命令)处理变量的内容,您可以这样做:

P_REP=$(sed 's/\./_/' <<< "$P")
于 2013-10-23T20:36:23.937 回答
0

对于循环,您可以使用:

#!/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[@]}
于 2013-10-23T20:32:57.353 回答
0

对于您提到的确切问题,请使用上面约翰的命题。

但是我要提一下,如果您不得不做一些无法用 bash 的模式替换语法解决的类似事情,那么您实际上不需要创建临时文件来使用 sed 或类似命令转换内容。首先,您可以将变量作为 STDIN 直接通过管道传输到程序。其次,您可以将命令的输出(或者它是 STDOUT、STDERR 或两者)直接输入到 shell 变量中。

因此,在您的示例中,您将拥有:

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

另请注意,数组语法(即{ '0.10', '0.20', ...})主要针对 Bash 和少数 Bash 追随者。当这样做很容易时,您可能更喜欢在 shell 中使用更经典的 for 循环方法,正如我在上面所展示的那样。然后您的代码将在所有符合 posix 的 shell 中安全地执行。

于 2013-10-23T20:39:41.370 回答
0

为什么这么复杂有一个简单的解决方案您正在更改文件夹/目录中的所有子字符串所有文件

ORG="orignal_string"
DES="destination_string"
find . -type f -exec sed -i 's/'"${ORG}"'/'"${DES}"'/g' {} +
于 2020-09-29T20:00:41.300 回答