Как поменять местами два слова с помощью sed и с несколькими разделителями?

В словах принимаются только буквы, любые другие символы являются разделителями. Я хочу поменять первое слово на третье слово.

sed -E 's/([A-Za-z]+) [^A-Za-z] ([A-Za-z]+) [^A-Za-z] ([A-Za-z]+)/\3 \2 \1/' filename

Я написал это, но работает неправильно

Пример:

I 4want5to%change

Эту строку я хочу изменить на:

to 4want5I%change

Есть идеи?

-1
12.04.2016, 05:18
3 ответа

Использование класса символов [[: alpha:]] для сопоставления верхнего и нижнего регистра и отрицания [^ [: alpha :]] для соответствия всем остальным:

sed -r 's/^([^[:alpha:]]*)([[:alpha:]]+)([^[:alpha:]]+[[:alpha:]]+[^[:alpha:]]+)([[:alpha:]]+)([^[:alpha:]]*)/\1\4\3\2\5/' file.txt

Пример:

$ sed -r 's/^([^[:alpha:]]*)([[:alpha:]]+)([^[:alpha:]]+[[:alpha:]]+[^[:alpha:]]+)([[:alpha:]]+)([^[:alpha:]]*)/\1\4\3\2\5/' <<<'I 4want5to%change'
to 4want5I%change

$ sed -r 's/^([^[:alpha:]]*)([[:alpha:]]+)([^[:alpha:]]+[[:alpha:]]+[^[:alpha:]]+)([[:alpha:]]+)([^[:alpha:]]*)/\1\4\3\2\5/' <<<'4I 4want5to%change'
4to 4want5I%change

$ sed -r 's/^([^[:alpha:]]*)([[:alpha:]]+)([^[:alpha:]]+[[:alpha:]]+[^[:alpha:]]+)([[:alpha:]]+)([^[:alpha:]]*)/\1\4\3\2\5/' <<<'Spring&summer^winter'
winter&summer^Spring
1
28.01.2020, 05:09

Если вы не состоите в браке с sed, это хорошая работа для perl: здесь я также предоставляю возможность указать, какие слова вы хотите поменять местами

, если "файл" содержит

I 4want5to%change
#One two three four
Spring&summer^winter

Затем эта команда

$ perl -lnse '
    BEGIN {
        $i = ($first - 1) * 2;
        $j = ($second - 1) * 2;
    }
    @tokens = /([[:alpha:]]*)([^[:alpha:]]*)/g;
    ($tokens[$i], $tokens[$j]) = ($tokens[$j], $tokens[$i]);
    print join "", @tokens;
' -- -first=1 -second=3 file

выводит

to 4want5I%change
two#One  three four
winter&summer^Spring
0
28.01.2020, 05:09

Уберите пробелы и исправьте обратные ссылки, чтобы сохранить разделители. Кроме того, поскольку у вас есть разделитель « <пробел> 4 », вам, очевидно, необходимо разрешить несколько символов «разделителей» в строке в качестве разделителей.

Вы должны указать, что это в начале строки.

Поэтому вместо:

sed -E 's/([A-Za-z]+) [^A-Za-z] ([A-Za-z]+) [^A-Za-z] ([A-Za-z]+)/\3 \2 \1/' filename

Используйте:

sed -E 's/^([A-Za-z]+)([^A-Za-z]+[A-Za-z]+[^A-Za-z]+)([A-Za-z]+)/\3\2\1/' filename
1
28.01.2020, 05:09

Теги

Похожие вопросы