Sed命令仅在所需位置更改字符串
Sed command to change a string at only desired place
我想在 bash 脚本中使用 sed
替换文件中的字符串,但该字符串出现在该文件的多个位置。
有没有什么方法可以使用 WHERE 子句替换字符串,这样我就可以只在需要的地方替换字符串?
使用行号不起作用,因为我需要一个比允许的更灵活的脚本。这是我正在尝试做的事情。
我将所需的代码片段存储在一个变量中。我可以在 sed
命令中使用该变量吗?例如,
sed -i "s/condition: succeeded('Fair_PreProd')/condition: succeeded('Fair_UAT')/g" $folder_path/$file_name
这是原始文件:
-stage: Moto_Dev
dependsOn: Build
condition: and(succeeded(), eq(variables.isDevelop, true))
- stage: Unity_Dev
dependsOn: Build
condition: and(succeeded(), eq(variables.isUnityDevelop, true))
- stage: QA
dependsOn: Dev
condition: succeeded('Dev')
- stage: UAT
dependsOn: Build
condition: and(succeeded(), eq(variables.isStaging, true))
dependsOn: Build
出现在 3 个地方。我只想替换 -stage:MotoDev
部分中的那个。我该怎么做?
建议读取 bash
个变量的 awk
解决方案。
filter
: awk
RegExp 过滤正确的行。
target
: 一个 awk
RegExp 来标识要替换的字符串
replacement:
一个字符串不是 RegExp 来替换目标 RegExp。
使用提供的示例:
awk '[=10=]~filter && [=10=]~target{gsub(target,replacement)}1' filter="block4" target="a=c" replacement="this = that" input.file
# same command, less readable, but shorter:
awk '[=10=]~f && [=10=]~t{gsub(t,r)}1' f="block4" t="a=c" r="this = that" input.file
这种方法的优点:
- 比
sed
更灵活。
- 通用:可以添加更多过滤器和过滤逻辑。
这种方法的缺点:
- 无法对输入文件进行 in-place 替换。喜欢
sed -i
- 因此需要一一明确指定所有文件。
示例输出:
awk '[=11=]~filter && [=11=]~target{gsub(target,replacement)}1' filter="block4" target="a=c" replacement="this = that" input.1.txt
block1{ a=c }
block2{ v=c }
block3{ w=c }
block4{ this = that }
block5{ a=c }
Is there any way to replace the string using a WHERE clause so I can replace the string only where I want?
sed
没有 SQL-style WHERE
子句,但是命令可以有“地址”来定义要操作的输入行的子集。这些可以采取多种形式。正则表达式可能是最常见的,但也有行号和一些特殊形式。您还可以包含从简单地址构建的 范围 。地址范围将是解决您提出的问题的一个相当好的方法。
例如,
sed -i '/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/ s/dependsOn: Build/dependsOn: Test/' input
解释:
-i
command-line标志告诉sed
工作“in-place”,这实际上意味着它将用一个文件替换原始文件包含 sed
的输出。
/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/
是一个范围地址,由一个用于范围开始的正则表达式 (/^\s*-\s*stage:\s*MotoDev/
) 和一个用于范围结束的正则表达式 (/^\s*-/
) 组成。
/^\s*-\s*stage:\s*Moto_Dev/
与您希望进行更改的部分的开头相匹配,在某些位置的白色 space 的确切数量具有一定的灵活性。为了简洁明了,它使用 \s
来表示单个 space 或制表符。那是一个 GNU 扩展,但是如果你不能依赖 GNU sed
那么还有其他方式来表达同样的事情。
/^\s*-/
匹配下一节的开头,因为您已经输入了。如果有必要更具选择性,它可以变得更具体。
该范围包括其端点,但这似乎不是手头任务的问题。
在显示的输入中只有一个这样的范围,并且该范围包含您要修改的行。对范围内的每一行执行指定的替换 s/dependsOn: Build/dependsOn: Test/
,但只有包含要替换的匹配项的那一行。该范围内的所有其他人将不受影响。
没有为范围外的行指定任何命令,因此它们也不受影响。
你也问了,
I stored the desired piece of code in a variable. Can I use that
variable in a sed
command? For example,
sed -i "s/condition: succeeded('Fair_PreProd')/condition: succeeded('Fair_UAT')/g" $folder_path/$file_name
sed
不会扩展 shell-style 参数引用,但您不需要它来做。该命令中的变量引用在执行结果命令之前由 shell 本身扩展,因此
- 是的,您可以使用它们,并且
- 这不是使用 shell 变量的问题,特别是
sed
。
我想在 bash 脚本中使用 sed
替换文件中的字符串,但该字符串出现在该文件的多个位置。
有没有什么方法可以使用 WHERE 子句替换字符串,这样我就可以只在需要的地方替换字符串?
使用行号不起作用,因为我需要一个比允许的更灵活的脚本。这是我正在尝试做的事情。
我将所需的代码片段存储在一个变量中。我可以在 sed
命令中使用该变量吗?例如,
sed -i "s/condition: succeeded('Fair_PreProd')/condition: succeeded('Fair_UAT')/g" $folder_path/$file_name
这是原始文件:
-stage: Moto_Dev
dependsOn: Build
condition: and(succeeded(), eq(variables.isDevelop, true))
- stage: Unity_Dev
dependsOn: Build
condition: and(succeeded(), eq(variables.isUnityDevelop, true))
- stage: QA
dependsOn: Dev
condition: succeeded('Dev')
- stage: UAT
dependsOn: Build
condition: and(succeeded(), eq(variables.isStaging, true))
dependsOn: Build
出现在 3 个地方。我只想替换 -stage:MotoDev
部分中的那个。我该怎么做?
建议读取 bash
个变量的 awk
解决方案。
filter
: awk
RegExp 过滤正确的行。
target
: 一个 awk
RegExp 来标识要替换的字符串
replacement:
一个字符串不是 RegExp 来替换目标 RegExp。
使用提供的示例:
awk '[=10=]~filter && [=10=]~target{gsub(target,replacement)}1' filter="block4" target="a=c" replacement="this = that" input.file
# same command, less readable, but shorter:
awk '[=10=]~f && [=10=]~t{gsub(t,r)}1' f="block4" t="a=c" r="this = that" input.file
这种方法的优点:
- 比
sed
更灵活。 - 通用:可以添加更多过滤器和过滤逻辑。
这种方法的缺点:
- 无法对输入文件进行 in-place 替换。喜欢
sed -i
- 因此需要一一明确指定所有文件。
示例输出:
awk '[=11=]~filter && [=11=]~target{gsub(target,replacement)}1' filter="block4" target="a=c" replacement="this = that" input.1.txt
block1{ a=c }
block2{ v=c }
block3{ w=c }
block4{ this = that }
block5{ a=c }
Is there any way to replace the string using a WHERE clause so I can replace the string only where I want?
sed
没有 SQL-style WHERE
子句,但是命令可以有“地址”来定义要操作的输入行的子集。这些可以采取多种形式。正则表达式可能是最常见的,但也有行号和一些特殊形式。您还可以包含从简单地址构建的 范围 。地址范围将是解决您提出的问题的一个相当好的方法。
例如,
sed -i '/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/ s/dependsOn: Build/dependsOn: Test/' input
解释:
-i
command-line标志告诉sed
工作“in-place”,这实际上意味着它将用一个文件替换原始文件包含sed
的输出。/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/
是一个范围地址,由一个用于范围开始的正则表达式 (/^\s*-\s*stage:\s*MotoDev/
) 和一个用于范围结束的正则表达式 (/^\s*-/
) 组成。/^\s*-\s*stage:\s*Moto_Dev/
与您希望进行更改的部分的开头相匹配,在某些位置的白色 space 的确切数量具有一定的灵活性。为了简洁明了,它使用\s
来表示单个 space 或制表符。那是一个 GNU 扩展,但是如果你不能依赖 GNUsed
那么还有其他方式来表达同样的事情。/^\s*-/
匹配下一节的开头,因为您已经输入了。如果有必要更具选择性,它可以变得更具体。 该范围包括其端点,但这似乎不是手头任务的问题。
在显示的输入中只有一个这样的范围,并且该范围包含您要修改的行。对范围内的每一行执行指定的替换
s/dependsOn: Build/dependsOn: Test/
,但只有包含要替换的匹配项的那一行。该范围内的所有其他人将不受影响。没有为范围外的行指定任何命令,因此它们也不受影响。
你也问了,
I stored the desired piece of code in a variable. Can I use that variable in a
sed
command? For example,sed -i "s/condition: succeeded('Fair_PreProd')/condition: succeeded('Fair_UAT')/g" $folder_path/$file_name
sed
不会扩展 shell-style 参数引用,但您不需要它来做。该命令中的变量引用在执行结果命令之前由 shell 本身扩展,因此
- 是的,您可以使用它们,并且
- 这不是使用 shell 变量的问题,特别是
sed
。