Вот мое решение на Python.
with open('/path/to/file', 'r') as f:
for line in f:
x=line.split(',')
y=x[4].split('|')
print(','.join(x[:4]) + ',' + str(min(y, key=lambda z: abs(float(z)-float(x[5])))))
Если у вас есть что-то вроде Pyed Piper, также известного как pyp
, вы можете запустить его прямо из командной строки терминала:https://code.google.com/archive/p/pyp/
a=`awk -F ":" '{print $1}' filename | perl -pne "s/\n/ /g"`
b=`awk -F ":" '{print $2}' filename | perl -pne "s/\n/ /g"`
awk -v a="$a" -v b="$b" '{print a":"b;exit}'
выход
ABC DEFG MJk : 123 4587 36
питон
#!/usr/bin/python
k=open('o.txt','r')
a=[]
b=[]
for i in k:
u=i.split(":")[0]
a.append(u)
z=i.split(":")[1]
b.append(z.strip())
print " ".join(a) +": "+ " ".join(b)
~
Казалось бы, нужно буферизовать весь контент. Вы можете попробовать следующее:
awk '{FNR==1{first=$1; second=$3} FNR>1{first=first " " $1; second=second " " $3} END{printf("%s : %s\n", first, second)}'
Это позволит аккумулировать содержимое всех «элементов первого столбца» всех строк в переменной first
, а содержимое «элементов второго столбца» (фактически третьего,потому что :
будет формировать собственный столбец с точки зрения awk
)в переменной second
. В конце он выводит накопленные таким образом буферы с символом-разделителем :
.
Если начальные/конечные пробелы не являются проблемой, вы можете сократить код до
awk '{first=first " " $1; second=second " " $3} END{printf("%s : %s\n", first, second)}'
Это можно сделать по-разному, но я оставлю свой ответ в качестве примера без использования awk
.
Предположим, что ваши данные находятся в файле data.dat
, тогда решение:
echo "$(cut -d ':' -f 1 data.dat | tr '\n' ' ' | xargs) : $(cut -d ':' -f 2 data.dat | tr '\n' ' ' | xargs)"
Я получил следующий результат:
ABC DEFG MJk : 123 4587 36
Давайте перейдем к объяснению:
cut -d ':' -f 1 data.dat
cut
— команда для получения части строки (, см.man cut
)-d ':'
сообщает, что мы используем двоеточие в качестве разделителя -f 1
указывает извлечь только первый столбец (все, что осталось от двоеточия в вашем случае)data.dat
— это просто имя файла при сохранении ваших исходных данных tr '\n' ' '
переводит новые строки изменений(\n
)в пробелы, соединяющие выходные строки в одну строку xargs
здесь как уловка -без каких-либо аргументов эта команда перепечатывает каждое слово, обрезая лишние пробелы Это почти то же самое со второй частью, за исключением того, что -f 2
используется для извлечения строки слева от двоеточия.
Мы используем команду echo
для вывода результатов($(...)
расширяет команду и помещает вывод команды в скобки в результате )двух анализов файла и соединяет их двоеточием между двумя проходами.
$ awk -F: '{a=a $1; b=b $2} END{print a FS b}' file
ABC DEFG MJk : 123 4587 36
В последнее время мы видим много сообщений, в которых люди используют tr '\n' ' '
или что-то подобное для преобразования новой строки во что-то другое. За исключением редких ситуаций, не делайте этого, так как он преобразует текстовый файл POSIX (, который могут читать все инструменты обработки текста POSIX ), во что-то другое, где YMMV. Текстовые строки POSIX заканчиваются на \n
, а текстовый файл POSIX состоит из текстовых строк POSIX.Если вы используете tr
или что-то еще, чтобы удалить все символы новой строки, то то, что любой последующий инструмент обработки текста POSIX (awk, sed и т. д. и т. д. )может сделать с этим в качестве ввода, является неопределенным поведением.
Вот пример другого поведения, которого вы, возможно, не ожидаете, но которое на самом деле определено POSIX. Допустим, мы хотим преобразовать эту многострочную строку -в одну строку, разделенную пробелом -:
.$ printf 'foo\nbar\n' | wc -l
2
с помощью tr
удалить все \n
с:
$ printf 'foo\nbar\n' | tr '\n' ' '
foo bar $
$ printf 'foo\nbar\n' | tr '\n' ' ' | wc -l
0
по сравнению с лучшим способом сделать то же самое, который выводит текстовый файл POSIX и, таким образом, дает более интуитивно понятный результат при передаче вwc
:
$ printf 'foo\nbar\n' | paste -sd ' ' -
foo bar
$ printf 'foo\nbar\n' | paste -sd ' ' - | wc -l
1
Я бы предпочел сохранить каждый столбец в массиве, а затем распечатать их в нужном формате
awk -F" : " '{a[NR]=$1;b[NR]=$2} END{ for(i=1;i<=NR;i++) printf "%s ",a[i]; printf ": "; for(i=1;i<=NR;i++) printf "%s ",b[i];}' file
-F" : "
разделяет столбцы на основе разделителя " : "
{a[NR]=$1;b[NR]=$2}
создает два массива: индексы =NR
(количество строк )и значения = значение столбца в этой строке printf
печатает в нужном порядке(printf
не печатаетnewline
)cut
иpaste
(и<()
):
paste -s -d ' ' <(cut -d : -f 1 file) <(cut -d : -f 2 file) | paste -s -d :
Прочитать файл дважды, cut
в соответствующие поля. paste
последовательно (дважды, сначала через пробел, затем через двоеточие ). paste -s
заменит <newline>
каждой строки, кроме последней, на разделитель. Если пробелы уже есть во входном файле, измените первый разделитель paste
на пустую строку -d ''
.
Это можно сделать с помощью редактора sed, добавив следующую строку в пространство шаблонов и перетасовав поля вокруг центрального двоеточия. Команда test повторяется до тех пор, пока не будет выбрана следующая строка.
sed -Ee '
:a;$!N;s/(.*):(.*)\n(.*):(.*)/\1\3:\2\4/;ta
' file
Версия awk говорит сама за себя.
awk -F ':' -v ORS='' '
{ a[NR] = $1; b[NR] = $2 }
END {
a[NR] = a[NR] FS
for (i=1; i<=2*NR; i++)
print i<=NR ? a[i] : b[i-NR]
print RS
}
' file
Результат:
ABC DEFG MJK : 123 4587 36