如何根据bash中特定字符串的存在进行操作?



我正在处理一个csv文件,所以假设我有这样一列:

5, 10,在11;20;& lt; 14

我想要的输出是:

5, 10, 12, 20; 13

所以我想在bash语言中对那些大于(>)符号的值加上+1,对那些小于(<)符号的值减去1。我用sed尝试了一些奇怪的东西,但考虑到它将这些更改解释为字符串,它没有成功。

有什么建议吗?

使用awk(使用GNUawk测试):

$ awk -F; -v OFS=; '
{
for(i = 1; i <= NF; i++) {
if($i ~ /^<[[:digit:]]+$/) {
sub(/^</,"",$i)
$i--
}
else if($i ~ /^>[[:digit:]]+$/) {
sub(/^>/,"",$i)
$i++
}
}
} 1' <<< "5;10;>11;20;<14"
5;10;12;20;13

警告:当且仅当您信任您的输入文件并且您100%确定它不包含恶意字段(请参阅最后注释)时使用以下字段。

对于GNUsed(假设您的shell是bash),有点短,但也有点难以理解(与sed一样):

$ sed -E '
s/<([[:digit:]]+)/$((1-1))/g
s/>([[:digit:]]+)/$((1+1))/g
s/.*/printf "%sn" "&"/e
' <<< "5;10;>11;20;<14"
5;10;12;20;13

也就是说(其中N是一串数字),将所有<N替换为$((N-1)),将所有>N替换为$((N+1)),将结果字符串S替换为printf "%sn" "S",用bash执行并替换为输出(这就是替换命令的e修饰符所做的)。在您的示例中,输入字符串依次变为:

5;10;>11;20;$((14-1))
5;10;$((11+1));20;$((14-1))
printf "%sn" "5;10;$((11+1));20;$((14-1))"
5;10;12;20;13

这里有一个严重的安全问题的原因是,如果你的一个字段是,例如,$(rm -rf ~/*),它会简单地递归删除你的整个主目录…因此,如果您不控制输入,请选择awk版本。

5;10;>11;20;<14

|

{m,g}awk '
BEGIN {
_*=(OFS= "") (__-=_^= FS ="("(
___="3117")"|"(____="1624")")+"
} {
gsub(";[<>][0-9]+",____ "&" ___)
gsub(____ ";[<>]", "&" ___)
NF
for(_+=(_^=($_=$_)<"")+_;_<=NF;_++) {
if ($_~"^[0-9]+$") {
$_+=__^($(_+__)~"[<]$")
}
} print $(_=_<_) }'

=

5;10;>12;20;<13

相关内容

  • 没有找到相关文章

最新更新