使用 sed 在 b 之前冒泡 a

使用 sed 在 b 之前冒泡 a

我有一个文件,其中仅包含 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”时,将其推到数组的末尾,否则放置在开头。最后我们打印数组。

相关内容