我有一个文本文件,里面有
!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 < $1
我尝试过awk分割,但它没有给出预期的输出。对此有什么变通办法吗?通过使用awk或sed。
以下假设您希望在!@#$%
集中的每个字符后面添加一个空格(即使它是一行中的最后一个字符(。测试文件:
$ 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
使用普通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 '%sn' "$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 '%sn' "$line"
done < file.txt
a! a
@ bb
c# c
$ dd
ee%
foo
% b% r
您在示例中称为特殊的字符似乎是GNUsed
的[[:punct:]]
字符的子集,因此我提出以下解决方案:
sed 's/([[:punct:]])/1 /g' file.txt
其中CCD_ 8内容为
!aa
@bb
#cc
$dd
%ee
输出
! aa
@ bb
# cc
$ dd
% ee
说明:我使用(
捕捉组。。。具有属于[:punct:]
的任何字符的)
,然后我用该捕获的内容和空格替换所捕获的内容。我使用g
将其应用于每行中的所有出现,尽管这对上面的数据没有明显的影响。如果您确定每行最多有一个字符要替换,则可以选择删除g
。
如果您想了解更多关于[:punct:]
或其他类似字符集的信息,请阅读Regular-Expressions.info 上的字符类
如果文件总是在这样的行的开头包含一个符号,那么使用这个
sed -Ei 's/^(.)/1 /g' yourfile.txt
-E
选项是告诉sed
使用regex。-i
以内联方式修改文件,如果您想输出到控制台或其他文件,可以将其删除。^(.)
正则表达式捕获行上的第一个字符,并为其添加一个空格(1
(
假设special characters
是非数字和非字母字符,并且行中可以出现特殊字符anywhere
,请使用以下正则表达式替换它们。
sed 's/[^a-zA-Z0-9]/& /g' urfile