如何在 bash 脚本中的特殊字符后添加 space?

How to add a space after special characters in bash script?

我有一个文本文件,其中包含

!aa
@bb
#cc
$dd
%ee

预期输出是,

! aa
@ bb
# cc
$ dd
% ee

我试过了,echo "${foo//@/@ }"

这对一个字符串确实有效,但不适用于文件中的所有行。我已经尝试使用这个 while 循环来读取文件的所有行并使用 echo 执行相同的操作但是它不起作用。

while IFS= read -r line; do
    foo=$line
    sep="!@#$%"
    echo "${foo//$sep/$sep }"
done < 

我试过使用 awk split 但它没有给出预期的输出。有什么解决方法吗?通过使用 awk 或 sed。

如果文件总是在行首包含一个符号,那么使用这个

sed -Ei 's/^(.)/ /g' yourfile.txt

-E选项是告诉sed使用正则表达式。 -i 修改内联文件,如果你想输出到控制台或另一个文件,你可以删除它。 ^(.) 正则表达式捕获行中的第一个字符并向其添加 space ( )

假设special characters是non-numeric和non-alphabetic字符,行中可以出现特殊字符anywhere,用下面的正则表达式替换。

sed 's/[^a-zA-Z0-9]/& /g' urfile

以下假定您要在 !@#$% 集中的每个字符后添加一个 space(即使它是一行中的最后一个字符)。测试文件:

$ cat file.txt
a!a
@bb
c#c
$dd
ee%
foo
%b%r
$ sep='!@#$%'

sed:

$ sed 's/['"$sep"']/& /g' file.txt
a! a
@ bb
c# c
$ dd
ee% 
foo
% b% r

awk:

$ awk '{gsub(/['"$sep"']/,"& "); print}' file.txt
a! a
@ bb
c# c
$ dd
ee% 
foo
% b% r

with plain bash(不推荐,太慢):

$ while IFS= read -r line; do
    str=""
    for (( i=0; i<${#line}; i++ )); do
      char="${line:i:1}"      
      str="$str$char"
      [[ "$char" =~ [$sep] ]] && str="$str "
    done
    printf '%s\n' "$str"
  done < file.txt
a! a
@ bb
c# c
$ dd
ee% 
foo
% b% r

或者(不确定哪个最差):

$ while IFS= read -r line; do
    for (( i=0; i<${#sep}; i++ )); do
      char="${sep:i:1}"
      line="${line//$char/$char }"
    done
    printf '%s\n' "$line"
  done < file.txt
a! a
@ bb
c# c
$ dd
ee% 
foo
% b% r

您在示例中调用 special 的字符似乎是 GNU sed 中称为 [[:punct:]] 的字符的子集,因此我提出以下解决方案:

sed 's/\([[:punct:]]\)/ /g' file.txt

其中file.txt内容为

!aa
@bb
#cc
$dd
%ee

输出

! aa
@ bb
# cc
$ dd
% ee

说明:我使用捕获组 \(...\),其中包含属于 [:punct:] 的任何字符,然后我用捕获的内容替换捕获的内容,然后是 space。我使用 g 将其应用于每一行中的所有出现,尽管这对上面的数据没有明显影响。如果您确定每一行中最多有一个字符要替换,您可以选择删除 g

如果您想了解有关 [:punct:] 或其他类似字符集的更多信息,请阅读 Character Classes on Regular-Expressions.info