sed:更新文件中的2个相似变量但保留大小写

sed:更新文件中的2个相似变量但保留大小写

我在一个文件中有 2 个变量,如下所示,我需要分配一个由一个用户输入插入的新值: read -p "Enter CName Name : " CName

sid=C02SBX
SID=C02SBX

当我运行以下 GNUsed语句时:

sed -i "s/sid=.*/sid=$CName/gI" dbca2.rsp

它将更新变量如下:

sid=C03SBX
sid=C03SBX

问题:我如何确保标志sid前的第二个=始终保持大写,例如SID=C03SBX第一个sid保持小写。另外,无论用户输入小写还是大写,符号后面的sid和都应始终为大写,例如 ( )?SID==C03SBX

答案1

通常,您不应该嵌入数据在里面代码语言解释器的参数,无论它们是 shell、sedawkperlpython等。

这样做总是会引入命令注入漏洞。

所以像sed -e "code $data", sh -c "code $data", eval "code $data", perl -e "code $data"(注意双倍的应该从词汇表中$var删除其中的 s 扩展为 shell 变量的内容的引号。

数据应该通过用于数据而不是代码的通道传递。sed(与shawk以及任何现代或不太现代的编程语言相反)没有这样的通道,因此唯一的选择是清理这些数据,但sed自 80 年代以来,又出现了更好的替代方案。

在这里,您可以使用:

perl -pi -s -e 's/\bsid=\K.*/\U$value/i' -- -value="$CName" -- "$file"

请注意 code 参数是如何固定的:s/\bsid=\K.*/\U$value/i,并且数据(shell 变量的内容$CName)作为单独的非代码参数传递,旨在传递值(通过分配给$valueperl 变量)。

另请注意:

  • -i(复制自perl)是 中的非标准选项sed
  • I命令的标志也是如此sed
  • 不需要,g因为将.*匹配到行尾,因此每行只能有一个替换。s/\bsid=\K\S*/\U$value/gi当我们匹配sid=后跟任意数量的非空白字符时,它可能是有意义的,然后它会sid=foo SID=bar在一行上更改为sid=new-value SID=new-value
  • perl(与将输入解释为在用户区域设置中编码的文本相反sed)默认情况下将每个字节视为一个字符,因此如果文件包含在用户区域设置中不形成有效字符的字节,它仍然可以正常工作。
  • \U(来自 ex/vi)将后面的内容转换为大写。请注意,默认情况下,它仅适用于 ASCII 字母。某些实现也支持,sed但不是全部,也不是标准的。或者,您可以让 shelltypeset -u CName在 ksh/zsh 中使用该值将值转换为大写,或者$CName:u在 tcsh/zsh 或${(U)CName}zsh 或${CName^^}bash 中使用。这些通常会解释区域设置编码中的文本,并根据区域设置规则更改大小写。例如,i可以更改为Iİ取决于语言环境,并且İ可以将其编码为 0xdd 字节或字节 0xc4 0xb0,具体取决于语言环境是使用 iso8859-9 还是 UTF-8 作为字符映射。
  • 注意\b对于b边界sid=foo,因此它与setsid=foo例如不匹配。某些实现也支持,sed而其他一些实现则用\</ \>(来自 ex/vi)或[[:<:]]/[[:>:]]代替。
  • \KK指定比赛中 ept的开始。对于旧版本的perl,您可以使用s/(sid=).*/$1\U$value/i,即捕获 sid=带括号的部分并在替换时调用它$1。或者使用后视操作符,s/(?<=sid=).*/\U$value/i但在我看来,它看起来有点太复杂了。
  • -s作为with的替代方案-var=value,您可以使用环境变量来传递数据:VALUE=$CName perl -pi -e 's/\bsid=\K.*/\U$ENV{VALUE}/i' -- "$file"。如果该值是敏感的并且不应在 的输出中暴露ps -Af,那么这将是更好的选择。这也是您在awk(那里)使用的方法,ENVIRON["VALUE"]因为其他值传递通道会破坏包含反斜杠的数据。
  • 要从用户读取任意字符串,语法为bashIFS= read -rp 'Prompt: ' varIFS= read -r 'var?Prompt: '其他类似 Korn 的 shell 中)。但提示用户通常不是最好的方法,因为它会使您的脚本更加难以自动化或使用相同的参数重用。通常最好将输入作为命令行参数,例如you-script thenewCN参数可用的位置$1,或者使用标准getopts内置命令进行正确的标准命令行解析。

答案2

使用分组\(...\)和引用(\1对于第一组、\2第二组等):

sed -i "s/\(sid=\).*/\1${CName^^}/gI" dbca2.rsp

为了将用户输入转换为大写,使用 shell:${var^^}

答案3

您可以不区分大小写地匹配要替换的行,但仅修改以 开头的部分=,而不是整行:

 sed -e "/^[Ss][Ii][Dd]=/s/=*/=${^^CName}/"

请注意,${^^…}要大写参数是Bash 功能,不是标准的 POSIX shell 结构。

相关内容