LINUX.ORG.RU

sed + awk. заменить текстовое поле


0

2
# cat file.txt
| *Name* | *Monday* | *Tuesday* | *Wednesday* | *Thursday* | *Friday* |
| qwe %EDITCELL{ "label, 0, qwe" }% | yes | yes | yes | yes | yes |
| asd %EDITCELL{ "label, 0, asd" }% | yes | yes | yes | yes | yes |
| zxc %EDITCELL{ "label, 0, zxc" }% | yes | yes | yes | yes | yes |

надо найти колонку для определенного дня недели и выполнить замену yes на no во всех строках.

для поиска этой колонки я использую:

# cat 1mon.sh
#!/bin/bash
FILE="file.txt"
MASS=(`sed '/^| /!d; /^| \*/d' $FILE | awk -F"|" '{print$3}'`)
   echo ${MASS[$i]}
# ./1mon.sh
yes
yes
yes
где print$3 - print$7 соответствуют колонкам Monday - Friday.

★★

Вот, набыдлокодил. Давно на awk не писал. На Перле, наверное, проще было бы.

#Проверял только на gawk
#Вызов: gawk -f <этот скрипт> -v day=<день> <файл>
#Например: gawk -f change-day.awk -v day=Wednesday days.txt
BEGIN {
	if(!day) {
		print "Абонент не отвечает или временно недоступен.";
		exit 1;
	}
	day = "*" day "*"
	FS="\\s*\\|\\s*"
	ORS=" | "
}

{
	if(!init) {
		for(i = 2; i <= NF; i++) {
			if($i == day) field = i;
		}
		if(!field) {
			printf("Нетути дня недели %s\n", day);
			exit 1;
		}
		printf("%s\n", $0)
		init = 1;
	}
	else {
		$field = "no";
		printf("| ")
		for(i = 1; i <= NF; i++) if($i != "") print $i;
		printf("\n")
	}
}

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

спасибо, но мне бы что-то доступней для понимания, например как-то прикрутить

sed '/^| /!d; /^| \*/d; s/yes/no/1' $FILE > nufile
чтоб он искал нужные строки и менял нужное по номеру совпадение: s/yes/no/1 - для понед, s/yes/no/2 - для втор и тд.

но в данном случае nufile будет содержать измененные строки только для найденных по шаблону строк, то есть содержимое файла потеряется.

nerve ★★
() автор топика

sed, awk... зачем эти сложности? Вот решение на почти чистом rc:

#!/usr/bin/env rc
file=file.txt

i='1'
oifs=$ifs
ifs='|'

days=`{sed 1q $file} while(! ~ $i '0' && ! ~ $i '7') {
    if(~ ' *'^$1^'* ' $days($i)) { nl=$i ; i='0' }
    if not ifs=$oifs i=`{ hoc -e $i+1 }
    ifs='|'
}

sed 1q $file
tail -n +2 $file | while(l=`{read}) {
    i='1' while(! ~ $i '0' && ! ~ $i '7') {
	if(~ $i $nl) echo -n '| no '
	if not echo -n '|'$l($i)

	ifs=$oifs i=`{hoc -e $i+1}
	ifs='|'
    }
    echo '|'
}
Как работает:
% ./test.rc Wednesday
| *Name* | *Monday* | *Tuesday* | *Wednesday* | *Thursday* | *Friday* |
| qwe %EDITCELL{ "label, 0, qwe" }% | yes | yes | no | yes | yes |
| asd %EDITCELL{ "label, 0, asd" }% | yes | yes | no | yes | yes |
| zxc %EDITCELL{ "label, 0, zxc" }% | yes | yes | no | yes | yes |

quantum-troll ★★★★★
()
Последнее исправление: quantum-troll (всего исправлений: 1)
cat file.txt | awk -F'|' 'BEGIN { OFS="|"; col=4 } ($col == " yes ") { $col = " no " } { print $0 }'
| *Name* | *Monday* | *Tuesday* | *Wednesday* | *Thursday* | *Friday* |
| qwe %EDITCELL{ "label, 0, qwe" }% | yes | no | yes | yes | yes |
| asd %EDITCELL{ "label, 0, asd" }% | yes | no | yes | yes | yes |
| zxc %EDITCELL{ "label, 0, zxc" }% | yes | no | yes | yes | yes |

Где col — это номер дня плюс 2.

unterwulf
()
Ответ на: комментарий от unterwulf

большое спасибо! не знаю как, но это работает

#!/bin/bash
SHELL=/bin/bash
FILE="file.txt"
cat $FILE | awk -F"|" 'BEGIN { OFS="|"; col=5 } ($col == " yes ") { $col = " no " } { print $0 }' > nufile
mv nufile $FILE
nerve ★★
() автор топика
Ответ на: комментарий от unterwulf

Где col — это номер дня плюс 2

Такие огороды ради того, чтобы влезло в одну строку? Лучше ведь $2 == " *Name* " ... Ну и значимость пробелов вызывает сомнения. И print $0 :). btw наверно лучше OFS и FS устанавливать рядом (оба снаружи / оба внутри).

Правда принципиально ничего лучше придумать не могу, разве что был бы встроенный transpose. Разве что just for fun:

eddie -mData.List.{Split,Utils} -lL 'map (intercalate "|") . transpose . map (\(dow:xs) -> dow : if "Monday" `isInfixOf` dow then map (replace "yes" "no") xs else xs) . transpose . map (splitOn "|")'
anonymous
()
Ответ на: комментарий от nerve

Прикрути виндавс, не мучай себя.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.