我有一个文件,其中仅包含 a 和 b。
aaaaaaaaaaaaaabbbbbb
abababaaaabbbaabababa
bbbbbaaaaaa
aaabbbabbbaaaabbaba
abababbabbababbbabbab
abababbababaabaaabbababbaba
bababbbababba
我想用 sed 将所有 a 排序在 b 之前,如下所示:
aaaaaaaaaaaaaabbbbbb
aaaaaaaaaaaabbbbbbbbb
aaaaaabbbbb
aaaaaaaaaabbbbbbbbb
aaaaaaaabbbbbbbbbbbbb
...
我尝试写这个脚本
for row in $(sed -n 'p' $1)
do
for k in $(seq $((${#row}-2)))
do
for j in $(seq $((${#row}-k-1)))
do
if [[ "${row:$j:1}" == a && "${row:$j+1:1}" == b ]]; then
sed -e "s/./a/$j+1/p" $row >> out.txt
fi
done
done
done
但它不起作用,我真的不知道如何让它发挥作用。但写完这个脚本后,我意识到,使用 sed 标签也许可以更轻松地做到这一点。
但我不知道,如何在 sed 中设置测试条件,检查“a”是否在“b”之前,或者如何在 sed 中设置循环数?
答案1
我创建了一个名为 test.txt 的文件并运行以下命令:
sed -e ':loop' -e 's/ba/ab/' -e 't loop' test.txt
答案2
一种稍微更有效的方法sed
:
sed 'h; s/b//g; x; s/a//g; H; x; s/\n//' file.txt
和perl
:
perl -lpe '$_ = y/b//dr . y/a//dr' file.txt
另一种方式perl
:
perl -lpe '$_ = join "", sort split //' file.txt
(这有效是因为"a" lt "b"
)。
使用 GNU awk
:
awk '{ print gensub(/b/, "", "g") gensub(/a/, "", "g") }' file.txt
和bash
:
while read -r line; do
printf '%s%s\n' "$( tr -d b <<<"$line" )" "$( tr -d a <<<"$line" )"
done <file.txt
答案3
if [[ "${row:$j:1}" == a ...
如果你要这样做,我想你可以在 shell 中完成所有这些:
while read -r s ; do
for (( i = 0 ; i < ${#s} ; i++ )) ; do
[ "${s:i:1}" = "a" ] && astr+=a || bstr+=b
done
echo "$astr$bstr"
done
答案4
perl -pe 's/(b+)(a+)/$2$1/ while /ba/' data.file
只要记录包含“b”后跟“a”,我们就会不断翻转当前记录中的蜜蜂和艾斯的“岛屿”。
perl -F\(b+\) -lne '
my @A;
splice @A, (/b/ ? @A : 0), 0, $_ for @F;
print @A;
' data.file
我们为读入的每个记录/行初始化一个数组@A。检查从记录中划分出的字段(存储在@F中),当它们包含“b”时,将其推到数组的末尾,否则放置在开头。最后我们打印数组。