使用 sed 更改特定行中的特定字符

Using sed in order to change a specific character in a specific line

我是 bash 的初学者,这是我的问题。我有一个这样的文件:

Azzzezzzezzzezzz...
Bzzzezzzezzzezzz...
Czzzezzzezzzezzz...

我尝试在脚本中编辑此文件。ABC 字母在所有文件中都是唯一的,每行只有一个字母。

我想用一个数字替换每行的第一个 e 可以是 :

我想循环这个以获得这种类型的结果

Azzz1zzz5zzz1zzz...
Bzzz2zzz4zzz5zzz...
Czzz3zzz6zzz3zzz...

这里的所有数字都是 0 到 9 之间的随机 int 变量。我真的需要首先在我的循环的第一个执行中替换 1,2,3,然后是 5,4,6,然后是 1,5,3 和等等。

我试过了

sed "0,/e/s/e//;0,/e/s/e//;0,/e/s/e//" /tmp/myfile

但是结果是这样的(因为我没有指定行)

Azzz1zzz2zzz3zzz...
Bzzzezzzezzzezzz...
Czzzezzzezzzezzz...

我注意到 sed -i "/A/ s/$/ezzz/" /tmp/myfile 会在 A 行的末尾添加 ezzz 所以我尝试了这个

sed -i "/A/ 0,/e/s/e//;/B/ 0,/e/s/e//;/C/ 0,/e/s/e//" /tmp/myfile

但是失败了

sed: -e expression #1, char 5: unknown command: `0'

我迷路了。

我在一个变量(我们称之为 number_of_e_per_line)中有 ABC 行中 e 的数量。

感谢您抽出宝贵的时间。

只需在匹配 A.

的行上应用 s 命令
sed '
  /^A/{ s/e//; }
  /^B/{ s/e//; }
  # or shorter
  /^C/s/e//
'

s 命令默认替换第一个匹配项。例如,您可以执行 s/s//2 替换第二个出现,s/e//g(如“全局”)替换所有出现。

0,/e/ 指定 行的范围 - 它从第一行开始过滤行,直到匹配 /e/.

的行

sed 不是 Bash 的一部分。它是一种独立的(原始的)编程语言,是一个非常标准的命令。参见 https://www.grymoire.com/Unix/Sed.html

从评论继续。 sed 在这里是一个糟糕的选择,除非你所有的文件只能有 3 行。原因是 sed 处理每一行,无法单独计算 'e'.

的出现次数

相反,将 sed 包装在脚本中并跟踪替换内容可以让您处理任何文件,无论行数如何。您只需循环并一次处理一行,例如

#!/bin/bash

[ -z "" ] && {  ## valiate one argument for filename provided
  printf "error: filename argument required.\nusage: %s filename\n" "./" >&2
  exit 1
}

[ -s "" ] || {  ## validate file exists and non-empty
  printf "error: file not found or empty '%s'.\n" ""
  exit 1
}

declare -i n=1    ## occurrence counter initialized 1

## loop reading each line
while read -r line || [ -n "$line" ]; do
  [[ $line =~ ^.*e.*$ ]] || continue    ## line has 'e' or get next
  sed "s/e/1/$n" <<< "$line"            ## substitute the 'n' occurence of 'e'
  ((n++))                               ## increment counter
done < ""

您的数据文件每行末尾有 "..." 表明您的文件比发布的代码段大。如果您有以 'A' - 'Z' 开头的行,您不想写 26 个单独的 /match/s/find/replace/ 替换。如果你有 3 到 26(或更多)之间的某个地方,你不想为你面对的每个新文件重写不同的 sed 表达式。

这就是为什么我说 sed 是一个糟糕的选择。你真的没有办法用 sed 使任务成为通用任务。使用脚本的缺点是它会成为一个糟糕的选择,因为您需要处理的记录数量会增加(超过 100000 条左右只是由于效率)

例子Use/Output

使用 replace-e-incremental.sh 中的脚本和 file 中的数据,您可以:

$ bash replace-e-incremental.sh file
Azzz1zzzezzzezzz...
Bzzzezzz1zzzezzz...
Czzzezzzezzz1zzz...

修改fileIn-Place

由于你在这里多次调用sed,你需要将文件的输出重定向到一个临时文件,然后用临时文件覆盖它来替换原来的文件,例如

$ bash replace-e-incremental.sh file > mytempfile && mv -f mytempfile file
$ cat file
Azzz1zzzezzzezzz...
Bzzzezzz1zzzezzz...
Czzzezzzezzz1zzz...