Разделить или соединить строки в Linux с помощью sed

У меня есть файл, который содержит следующую информацию

$ cat test.txt 
Studentename:Ram
rollno:12
subjects:6
Highest:95
Lowest:65
Studentename:Krish
rollno:13
subjects:6
Highest:90
Lowest:45
Studentename:Sam
rollno:14
subjects:6
Highest:75
Lowest:65

Я пытаюсь разместить информацию об одном студенте в файле single. т.е. мой вывод должен быть

Studentename:Ram rollno:12 subjects:6 Highest:95 Lowest:65
Studentename:Krish rollno:13 subjects:6 Highest:90 Lowest:45
Studentename:Sam rollno:14 subjects:6 Highest:75 Lowest:65.

Ниже приведена команда, которую я написал

cat test.txt | tr "\n" " " | sed 's/Lowest:[0-9]\+/Lowest:[0:9]\n/g'

Вышеупомянутая команда разрывает строку в регулярном выражении Lowest: [0-9], но не печатает шаблон. Вместо этого он печатает Lowest: [0-9].

Пожалуйста помоги


person sudhir    schedule 13.02.2018    source источник
comment
Выглядит ли входной файл именно так с такими пустыми строками???   -  person Gilles Quenot    schedule 13.02.2018
comment
@GillesQuenot Я просто удалил пустые строки, потому что, по моему опыту, людям, плохо знакомым с SO, требуется некоторое время, чтобы обнаружить кнопку форматирования кода: {}. Если я ошибся, надеюсь, ОП меня быстро поправит.   -  person John1024    schedule 13.02.2018
comment
В основном файл содержит пустые строки   -  person sudhir    schedule 13.02.2018


Ответы (4)


Пытаться:

$ sed '/^Studente/{:a; N; /Lowest/!ba; s/\n/ /g}' test.txt
Studentename:Ram rollno:12 subjects:6 Highest:95 Lowest:65
Studentename:Krish rollno:13 subjects:6 Highest:90 Lowest:45
Studentename:Sam rollno:14 subjects:6 Highest:75 Lowest:65

Как это устроено

/^Studente/{...} указывает sed выполнять команды внутри фигурных скобок только в строках, начинающихся с Studente. Эти команды:

  • :a

    Это определяет метку a.

  • N

    Это читается в следующей строке и добавляется к пространству шаблонов.

  • /Lowest/!ba

    Если текущее пространство шаблонов не содержит Lowest, это указывает sed вернуться к метке a.

    Более подробно, /Lowest/ истинно, если строка содержит Lowest. В sed ! является отрицанием, поэтому /Lowest/! is true if the line does not containLowest. Inba, thebstands for the branch command anda` является меткой для перехода.

  • s/\n/ /g

    Это говорит sed заменить все символы новой строки пробелами.

person John1024    schedule 13.02.2018
comment
Когда дело доходит до условных выражений, awk более читабелен :) - person Gilles Quenot; 13.02.2018
comment
Спасибо за подробное объяснение. - person sudhir; 13.02.2018
comment
Будьте осторожны с ложными срабатываниями. Меня зовут Lowest - person potong; 13.02.2018

Попробуйте это, используя awk :

awk '{if ($1 !~ /^Lowest/) {printf "%s ", $0} else {print}}' file.txt

Или короче, но более запутанно:

awk '$1!~/^Lowest/{printf"%s ",$0;next}1' file.txt

Или исправить вашу команду:

tr "\n" " " < file.txt | sed 's/Lowest:[0-9]\+/&\n/g'

Объяснение: & соответствует левой части подстановки

person Gilles Quenot    schedule 13.02.2018
comment
Это то, что я ищу. Я пропустил &. Большое спасибо - person sudhir; 13.02.2018
comment
Поскольку ваш ответ работает хорошо, а также потому, что анонимный голосующий не оставил причин для своих отрицательных голосов: +1. - person John1024; 13.02.2018

Другой возможный вариант GNU sed, который не предполагает Самое низкое — последний элемент:

sed ':a; N; /\nStudent/{P; D}; s/\n/ /; ba' test.txt
person PesaThe    schedule 13.02.2018
comment
Вы получаете +1 от меня, потому что ваш ответ креативен, работает и не заслуживает чистой отрицательной оценки из-за какого-то анонимного голосующего, который не оставил сообщения ни в одном из наших ответов. - person John1024; 13.02.2018

Это может сработать для вас (GNU sed):

sed '/^Studentename:/{:a;x;s/\n/ /gp;d};H;$ba;d' file

Используйте пространство для удержания, чтобы собрать поля, а затем удалите символы новой строки, чтобы создать запись.

person potong    schedule 13.02.2018