Конкатенация непоследовательных линий в Баш - PullRequest
1 голос
/ 04 августа 2011

Для объединения последовательных строк я обнаружил, что это опубликовано Kanaka и GhostDog74:

while read line; do echo -n $line; [ "${i}" ] && echo && i= || i=1 ; done < File

Прекрасно работает, но я бы хотел изменить это, чтобы объединить текущую строку и четвертую строку за ней следующим образом:

line1
line2
line3
line4
line5
line6
line7

line1,line4
line2,line5
line3,line6
etc.  

Любая помощь будет высоко ценится.

Ответы [ 6 ]

2 голосов
/ 04 августа 2011
printf "%s\n" line1 line2 line3 line4 line5 line6 line7 line8  | 
awk 'NR > 3 {print prev3 ", " $0} {prev3=prev2; prev2=prev1; prev1=$0} '

производит

line1, line4
line2, line5
line3, line6
line4, line7
line5, line8
1 голос
/ 05 августа 2011

Использование массива в bash:

declare -a arr; arr=($(< line1to7))
for n in {0..3} ; do echo ${arr[n]}","${arr[$n+3]} ; done
line1,line4
line2,line5
line3,line6
line4,line7
1 голос
/ 05 августа 2011

Начало редактирования

Более простое решение, чем приведенное ниже, которое также легко модифицируется, чтобы взять N-ю строку вперед, всегда в седе:

<command that output something> | sed -n -e '1h;2,3H;4,${H;g;s/\n.*\n/,/;p;g;s/^[^\n]*\n//;h}'

И объясненная версия, которую можно запустить с sed -n -f script:

# Do not put a \n in front of the hold space for the 1st line.
1h
# For all lines except the 1st, append to the hold space.
2,$H
# From the 1st line than need to be append to another line, 4 in this case, ...
4,${
# Copy the hold space in the patter space, replace all what is between \n by ',', and print.
g
s/\n.*\n/,/
p
# Remove the 1st line from the hold space.
g
s/^[^\n]*\n//
h}

Конец редактирования

Кроме того, решение sed без файла:

<command that output something> | sed -n -e 'H;g;s/^\n\(.*\)\n\(.*\n.*\n\)\(.*\)$/\1,\3\n\2\3/;t next;b;:next;P;s/^[^\n]*//;h'

Как и все зашифрованное решение sed, оно заслуживает объяснения, которое я даю в виде закомментированного файла сценария sed, который можно запустить с sed -n -f script:

# Append current line to the hold space and copy the hold space in the pattern space.
H
g
# Now, the hold and pattern space contain '\n<line1>\n<line2>...'.
# If we can match 4 lines in the pattern space, append 1st and 4th line at the beginning of the pattern space and remove the 1st line.
# If no substitution occurs, start next cycle, else print the concatenation, remove the concatenation from the pattern space, and copy the pattern space in the hold space for next cycle.
s/^\n\(.*\)\n\(.*\n.*\n\)\(.*\)$/\1,\3\n\2\3/
t next
b
:next
P
s/^[^\n]*//
h
1 голос
/ 05 августа 2011

Кроме того, в чистом bash без использования файла:

<command that output something> | (read l1; read l2; read l3; while read l4; do echo "$l1,$l4"; l1=$l2; l2=$l3; l3=$l4; done)

Редактировать:

Масштабируемое решение в чистом bash (измените значение n для измененияза N-й строкой стоит cat с текущей строкой):

<command that output something> | (n=3; i=0; 
while [ $i -lt $n ]; do read line[$i]; i=$((i+1)); done;
while read line[$n]; do
  echo "${line[0]},${line[$n]}";
  i=0; while [ $i -lt $n ]; do line[$i]=${line[$((i+1))]}; i=$((i+1)); done;
done)
1 голос
/ 05 августа 2011

Если данные находятся в файле '<data file>':

tail -n +4 <data file> | paste -d ',' <data file> - | head -n -3
  • Команда 'tail' удаляет первые 3 строки '<data file>',
  • Команда 'paste' объединяет '<data file>' с результатом 'tail' с разделителем ',',
  • А команда 'head' удаляет последние 3 строки 'paste', которые ничего не используют из 'tail'.
0 голосов
/ 05 августа 2011

Я бы, вероятно, использовал Perl, но вы почти наверняка могли бы использовать и Python.

use strict;
use warnings;
my(@lines);
while (<>)
{
    chomp;
    if (scalar @lines >= 4)
    {
        my $old = shift @lines;
        print "$old,$_\n";
    }
    push @lines, $_;
}

С учетом нестандартной команды range для генерации строк с 1 по 20 и сценария Perl в xxx.pl это дает:

$ range -f 'line%d' 1 20 | perl xxx.pl
line1,line5
line2,line6
line3,line7
line4,line8
line5,line9
line6,line10
line7,line11
line8,line12
line9,line13
line10,line14
line11,line15
line12,line16
line13,line17
line14,line18
line15,line19
line16,line20
$

Если это не то, что вы хотите, вам нужно объяснить более четко, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...