Вопрос интересен только в том случае, если разделители не обязательно находятся в одной строке. Это можно сделать несколькими способами (даже с sed
), но awk
более гибок:
#!/bin/sh awk ' BEGIN { found = 0; } /xxx/ { if (!found) { found = 1; $0 = substr($0, index($0, "xxx") + 3); } } /yyy/ { if (found) { found = 2; $0 = substr($0, 0, index($0, "yyy") - 1); } } { if (found) { print; if (found == 2) found = 0; } } '
Это легко проверяется для случаев, когда в строке находится не более одной подстроки, используя эти данные:
this is xxx yy first second yyy xxx.x yyy xxx#yyy
и этот вывод (сценарий - «foo», данные - «foo.in "):
$ cat foo.in|./foo yy first second .x #
Принцип работы заключается в том, что входные данные находятся в $ 0
, а awk последовательно соответствует шаблонам xxx
и yyy
, позволяя более чем одной вещи изменять $ 0
на пути к последнему шагу, где он печатается.
Между прочим, этот пример не будет работать для
xxxxHelloyyyxxxWorldyyy
, поскольку он проверяет только первое совпадение . Сценарий Perl даст разные результаты, поскольку он использует жадное сопоставление, а не индекс / подстроку, который я использовал в примере с awk. Perl, конечно, может делать то же самое - с помощью сценария.
Awk (например, Perl) имеет свободный формат, поэтому команду можно выразить как что-то вроде
awk 'BEGIN{found=0;}/xxx/{if(!found){found=1;$0=substr($0,index($0, "xxx")+3);}}/yyy/{if(found){found=2;$0=substr($0,0,index($0,"yyy")-1);}}{ if(found){print;if(found==2)found=0;}}'
, но это делается редко, за исключением примера. Точно так же скрипты sed
(строчно-ориентированные) могут быть объединены в одну строку с некоторыми ограничениями. Опять же, сложные сценарии в sed
редко обрабатываются таким образом. Скорее, они рассматриваются как настоящие программы (см. пример ).
Дальнейшее повторное ading:
Используйтеtr
:
$ <input.txt tr "\n" ","
8600,22007,93509,9984,22146,
Вы можете использоватьtr
tr '\n',
Это изменит каждый экземпляр \n
на запятую, поэтому вам нужно исправить последний. Вот пример
cat >file.txt <<x
8600
22007
93509
9984
22146
x
tr '\n', <file.txt
8600,22007,93509,9984,22146, # and the shell prompt follows immediately
tr '\n', <file.txt | sed 's/,$/\n/'
8600,22007,93509,9984,22146 # line is ended with newline
Обратите внимание, что такое использование sed
не определено стандартом POSIX, который предполагает, что все строки завершаются символом новой строки. Вы можете исправить это, вставив awk 1
в конвейер, потому что awk
явно определено POSIX для добавления завершающей новой строки к последней строке, если она отсутствует:
tr '\n', <file.txt | awk 1 | sed 's/,$//'
8600,22007,93509,9984,22146 # line is ended with newline
Для быстрого исправления это было бы приемлемым (хотя paste
решение, предлагаемое в другом месте, лучше ). Однако tr | awk | sed
— уродливая комбинация, которую следует пересмотреть в производственном коде. Таким образом, мы можем закончить с этим:
awk 'NR>1 {printf ","}; {printf "%s", $0}; END {printf "\n"}' file.txt
одной командой paste
:
paste -d, -s infile
-s
дает команду печатать строки в s erial с -d,
через запятую.
Если вы хотите сделать это в чистом Bash, вы можете:
ar=( $(<filename) )
( IFS=, echo "${ar[*]}" > filename )
Это создает массив, ar
, с разделяемыми пробелами -словами filename
в качестве элементов, а затем распечатывает его с запятыми между элементами. Все они построены -на функциях Bash.
Если у вас странные символы (, например.*
)в ваших строках данных это будет работать неправильно, но для ваших данных это работает.
Вы также можете использовать
tmp=$(printf '%s,' $(<filename))
printf '%s\n' "${tmp%,}" > filename
для того же эффекта.
Используя GNU sed
и предполагая, что в среде нет POSIXLY_CORRECT
переменной или если она есть, то ввод состоит как минимум из двух строк:
sed ':a;N;$!ba;s/\n/,/g' input.txt
мы не можем заменить новую строку . Но мы можем сделать это, добавив всю строку, как указано выше.....
Метод 1:
perl -pe 's/\n/,/ unless eof' filename
выход
8600,22007,93509,9984,22146
Метод 2 (Использование Python)
#!/usr/bin/python
m=open('file.txt','r')
j=[]
for i in m:
j.append(i.strip())
print ",".join(j)
выход
python i.py
8600,22007,93509,9984,22146
Вы можете сделать это преобразование несколькими способами, некоторые из них:
$ (head -n -1 - | tr \\n, ;cat -;) < inp
$ perl -lp -0777e 'chop;tr/\n/,/' inp
$ awk '$1=$1' FS="\n" RS= OFS=, inp
$ awk '{
p = $0
while ( getline > 0 ) p = p RS $0
$0 = p
gsub(/\n/, ",")
}1' inp
POSIX -СЭД:
$ sed -e '
:a
${s/\n/,/g;q;}
N;ba
' inp
ГНУ -СЭД:
$ sed -e '
$!{
N
s/^/\n/;D
}
y/\n/,/
' inp
$ perl -0777 -pe 's/\n(?!\z)/,/g' inp
$ perl -lpe '$\ = eof ? $/ : ","' inp