Вы можете использовать собственные операции со строками оболочки:
TEST="test 1234 foo"
SPLIT_VAR=${TEST/ */ }
Он заменит первое совпадение с шаблоном " *" (на один пробел, а затем что угодно )и заменит его на " " (на один пробел ). Таким образом, вы сохраняете первое слово и первый пробел.
См.http://www.tldp.org/LDP/abs/html/string-manipulation.htmlдля получения дополнительной информации об использовании манипуляций со строками.
И в качестве примечания, это также работает менее развитая оболочка (, протестированная на реализации ash в busybox ).
awk -F, -v OFS=, '{split("",q);for(i=j=1;i<=NF;i++){if(split($i,a,/\$/)>1){j++;$i=a[1];q[i]=a[2]}}print;if(j>1){for(i in q)$i=q[i];print}}' file
Или, расширенный:
awk -F, -v OFS=, '{
split("", q) # clear the q array; delete q is non-standard
for(i = j = 1; i <= NF; i++){
if(split($i, a, /\$/) > 1){ # if the field contains a $
j++ # increase the cnt of fields with a $
$i = a[1] # set the field to the part before the $
q[i] = a[2] # save the part after the $ in the q array
}
}
print # print the line with the parts before $
if(j > 1){ # if any field had a $
for(i in q) # for each field which had a $
$i = q[i] # replace it with the part after $
print # re-print the line with the parts after $
}
}' file
$ perl -F, -lane '$,=",";
print,next unless /\$/;
for(@F) {
my @e = split /\$/;
push @A, @e ? $e[0] : $_;
push @B, @e ? $e[1] : $_;
}
print splice @$_ for \(@A, @B);
' file.csv
краткая работа:
только строки, в которых есть литерал $, мы перебираем поля и разбиваем поле на два, в которых есть $.
Затем заполните два массива A и B
Наконец, распечатайте и очистите массивы AB для следующей записи.
Если я правильно понимаю, что некоторые поля являются «двойными» полями вариантов, разделенными $
, и вам просто нужны две копии этих строк, первая строка которых содержит первый вариант, а вторая строка — второй вариант...
awk '{v1=$0; gsub(/\$[^,]+/,""); gsub (/,[^,]+\$/,",",v1); print $0; if (v1!=$0) print v1}' file1
IMSI,MSISDN,SUBCATEGY,EPCMMEHOST,EPCMMEREALM,EPCROAMSCH,PSROAMSCH,OINR,MSCNUMBER,VLRNUMBER,SGSNNUMBER,EPCAPNNAME,EPCAPNAMBRUP,EPCAPNAMBRDOWN,EPCAMBRUP,EPCAMBRDOWN,CHARGE,EPCCHARGCHRT
NAN,NAN,2,,,0,,0,,,,OLAP,200000000,400000000,200000000,400000000,5,5
NAN,NAN,2,,,0,,0,,,,DOLAP,2048000,2048000,200000000,400000000,5,5
Я предполагаю, что точка, упомянутая @Paul _Pedant, действительно была опечаткой, и поле OLAP$DOLAP
также должно быть разделено. В этом случае может работать следующая awk
программа (назовем ееsplitfields.awk
):
#/usr/bin/awk -f
{
copy=0;
for (i=1;i<=NF;i++)
{
j=index($i,"$");
if (j>0)
{
fields[i]=substr($i,j+1);
$i=substr($i,1,j-1);
copy=1
}
else fields[i]=$i;
}
print;
if (copy==1)
{
for (i=1;i<NF;i++) printf("%s%s",fields[i],OFS);
printf("%s%s",fields[NF],ORS)
}
}
Вы можете использовать его, позвонив по телефону
user@host~$ awk -F, -v OFS="," -f splitfields.awk input.csv
Сценарий проверяет каждое поле на наличие знака $
и создает копию этого поля в массиве fields
для возможного дальнейшего использования. Если $
найдено,соответствующее поле текущей строки сокращается до части до до $
, а соответствующая запись в массиве fields
заполняется частью после $
.
После этой проверки в любом случае печатается (возможно измененная )текущая строка. Кроме того, если какое-либо из полей содержало знак $
, новая строка, состоящая из содержимого массива fields
, печатается в формате CSV.