如果我有一行:
There are seven pencil
我想将其打印为:
Ther a svn pcil
bash shell 命令是什么?
澄清:目标是删除所有至少两次出现的字母(第一次出现除外)。
答案1
基于 sed 经典 Syntax s/replace-this/with-that/g
whereg
意味着全局替换=所有发生,有人可以使用which2g
而不是g
which global replacement but after second occurence
(这是一个gnu sed
扩展)。
仅删除的示例e
:
$ echo $a
there are seven pencil
$ echo $a | sed 's/e//2g'
ther ar svn pncil
要删除所有重复的字母,我们可以使用这样的技巧:
$ sed -f <(printf 's/%s//2g\n' {a..z}) <<<"$a"
ther a svn pcil
不幸的是,这行不通:sed 's/[a-z]//2g'
上面的技巧使用了<( )
可以用作文件的进程替换。
在我的解决方案中,过程替换被视为脚本文件,由option = read sed 命令从文件sed
提供。sed
-f
答案2
Awk
解决方案(对于区分大小写的情况):
s="There are seven pencil"
printf '%s\n' "$s" | awk -v FS="" '{
for(i=1; i<=NF; i++)
if ($i==" " || !a[$i]++) printf "%s", $i; print ""
}'
-v FS=""
- 设置“空”字段分隔符,以便每个字符成为一个单独的字段(不是 POSIX,而是许多实现支持的 GNU 扩展)for(i=1; i<=NF; i++)
- 迭代字符if ($i==" " || !a[$i]++)
- 如果是空格字符或第一次出现某个字符
输出:
Ther a svn pcil
对于不区分大小写的情况,替换a[$i]
为a[tolower($i)]
.
答案3
这是 Bash 本身。
s="There are seven pencil"
declare -A A
while IFS= read -rn1 a; do
[ -z "$a" ] || [ -n "${A[$a]}" ] && continue
printf %s "$a"
[ "$a" == " " ] || A[$a]=x
done <<<"$s"
echo
逐行解释:
将字符串分配给变量
s="There are seven pencil"
声明一个关联数组
A
declare -A A
这个有点复杂。但没有详细信息,它按单个字符读取字符串并将刚刚读取的字符分配给
a
。这是一个while
循环。while IFS= read -rn1 a; do
如果当前字符为空 (
[ -z "$a" ]
) 或 (||
) 如果与此键(此字符)关联的值已被设置(如果已设置,则此处出现),则继续循环(转到下一次迭代,因此读取下一个字符)再次,所以我们继续而不打印它)。[ -z "$a" ] || [ -n "${A[$a]}" ] && continue
打印当前字符。
printf %s "$a"
如果字符是空格 - 那么不执行
A[$a]=x
- 这就是||
这里的意思。A[$a]=x
是关联操作。为了防止出现所有空格,不应为数组中的键空间分配任何值A
。 (参见第 4 点。)[ "$a" == " " ] || A[$a]=x
这结束了
while
循环。<<<"$s"
是这里字符串重定向。它用字符串填充循环。done <<<"$s"
最后
echo
打印行分隔符。printf
在第 5 点中,仅打印字符。如果没有这个,echo
输出将出现在与以下 shell 提示符相同的行上。把它取下来看看你自己。echo
答案4
另一个sed
解决方案:
对于单个字母字符:
$ echo 'here hear' | sed 's/\(\([[:alpha:]]\).*\)\2/\1' here ear
对于所有这些,该
g
标志都没有帮助,因为已经处理的字符不会再次检查。因此,使用循环 - 只要替换成功,“t”就会分支到标签$ echo There are seven pencils | sed -e :a -e 's/\(\([[:alpha:]]\).*\)\2/\1/; ta' Ther a svn pcil
使用 GNU
sed
,您可以将其缩短为:sed -E ':a;s/(([[:alpha:]]).*)\2/\1;ta'
忽略大小写(仍然使用 GNU sed
):
$ echo 'There this That' | sed -E ':a; s/(([[:alpha:]]).*)\2/\1/i; ta'
Ther is a
其中perl
(此处仅限 ASCII 字母):
$ echo 'There are seven pencil' | perl -pe 'while(s/([a-zA-Z]).*?\K\1//g){}'
Ther a svn pcil
$ echo 'There this That' | perl -pe 'while(s/([a-z]).*?\K\1//gi){}'
Ther is a