Как напечатать первый столбец следующей строки в текущей строке?


8

У меня есть такой файл:

abc 123    
abc 789  
bcd 456  
acb 135

Я хотел бы напечатать первый столбец следующей строки в текущей строке.

Желаемый вывод:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 

Я предпочитаю использовать awk.

Ответы:


16

Запомните предыдущую строку:

awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'

Это обрабатывает ввод следующим образом:

  • если текущая строка является второй или большей, выведите предыдущую строку (сохраненную в prev, см. следующий шаг) и первое поле текущей строки, разделенные разделителем выходного поля (по умолчанию символ пробела);
  • во всех случаях сохраняйте текущую строку в prevпеременной;
  • в конце файла выведите предыдущую строку.

11

Альтернативный awkподход:

$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt                                    
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

Это работает просто: первая строка - это особый случай - мы печатаем ее без новой строки и сообщаем awk перейти на следующую строку без выполнения других блоков кода. После этого NR == 1{printf "%s", $0;next}пропускается, но другие части делают работу.

Помните, что до сих пор мы печатали отформатированную строку без символа новой строки. Таким образом, printf " %s\n%s",$1,$0сейчас выполняется вывод первого слова (и поскольку новой строки не было, она остается на той же строке вывода), вставляется новая строка, а затем вся строка (но не заканчивается символом новой строки) , Таким образом, следующее первое введенное слово останется в той же строке. Процесс продолжается и продолжается, пока мы не достигнем конца файла.

Возможное улучшение состоит в том, чтобы включить END{print ""}блок для вставки последней строки. В некоторых случаях, когда полученный файл должен обрабатываться другими сценариями, это может быть желательно.


Хотя пользователь специально запрашивал AWK, такой же подход к печати форматированных строк можно использовать и с другими языками, например Python. Альтернатива Python предназначена для тех, кому интересно, как это можно реализовать на других языках:

#!/usr/bin/env python
from __future__ import print_function
import sys

old = None
for index,line in enumerate(sys.stdin):
    if index == 0:
        print(line.strip(),end=" ")
        continue
    words = line.strip().split()
    print(words[0] + "\n" + line.strip(),end=" ")

И использование вроде так:

$ ./append_first.py < input.txt                            
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

Та же самая идея о заключительном переводе строки применяется здесь.


9

Вот уродливый sedспособ просто для удовольствия

sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135 

объяснение

  • 2,$ от второй строки до последней
  • s/[^ ]\+/& &/ удвоить первый набор непробельных символов
  • ; разделяет команды, как в оболочке
  • s/ /\n/ заменить первый пробел новой строкой
  • paste -d ' ' - - склеить этот беспорядок (добавить вторую строку к третьей, четвертую строку к третьей и т. д.)

1
В качестве альтернативы вы можете использовать sedсамостоятельно без paste:sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt
Цифровой травмы

1
Если вы пишете sedпрограммы для развлечения, то, возможно, вам стоит попробовать себя в code-golf ;-)
Digital Trauma

1
@DigitalTrauma она уже два месяца занимается код-гольфом;)
Сергей Колодяжный

1

На мой взгляд, самый простой и читаемый подход:

  1. извлечь первый столбец ( cut)
  2. удалить первую строку из вашего извлеченного столбца ( tail)
  3. вставьте этот столбец в ваш исходный файл ( paste)

Пример: ваш пример выходного файла:

abc 123    
abc 789  
bcd 456  
acb 135

Затем выполните следующую команду в терминале

cut -d' ' -f1 in.txt | tail -n +2 | paste -d' ' file -

Вывод:

abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

Структура этого решения отличается от приведенных ответов. Нет необходимости условий, циклов или регулярных выражений.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.