Есть ли причина, по которой вы используете исключительно awk? Чтобы решить вашу проблему, вам нужно сначала разделить данные на каждую единицу, отсортировать, удалить дубликаты, а затем воссоединиться. Хотя вы можете сделать это с помощью любого подходящего языка программирования или сценариев (, даже C ), действительно ли стоит изобретать велосипед, когда уже есть инструменты, способные делать то, что вам нужно?
Если опубликованные вами данные являются реальным представлением данных, с которыми вы работаете, вы можете быстро обработать их с помощью следующих команд:
$ cat RAW_DATA
<ITEM ID='81'>,< 1>KWIKSET</1>,< 2>PASS</2>,< 7>KNOB</7>,< 5a>RIGHT</5a>,< 8c>BRASS</8c>,< 2>TYLO</2>,< 2>PASS</2>,< 5a>RIGHT</5a>,< 8c>BRASS</8c>
<ITEM ID='82'>,< 1>KWIKSET</1>,< 4a>PRIVACY</4a>,< 7>KNOB</7>,< 8b>SATIN</8b>,< 8c>CHROME</8c>,< 2>TYLO</2>,< 4a>PRIVACY</4a>,< 8b>SATIN</8b>,< 8c>CHROME</8c>
<ITEM ID='83'>,< 1>KWIKSET</1>,< 8b>POLISHED</8b>,< 8c>BRASS</8c>
$ while read line; do echo "$(cut -d, -f1 <<< "$line"),$(cut -d, -f2- <<< "$line" | tr ',' '\n' | sort -n | uniq | paste -sd,)"; done < RAW_DATA
<ITEM ID='81'>,< 1>KWIKSET</1>,< 2>PASS</2>,< 2>TYLO</2>,< 5a>RIGHT</5a>,< 7>KNOB</7>,< 8c>BRASS</8c>
<ITEM ID='82'>,< 1>KWIKSET</1>,< 2>TYLO</2>,< 4a>PRIVACY</4a>,< 7>KNOB</7>,< 8b>SATIN</8b>,< 8c>CHROME</8c>
<ITEM ID='83'>,< 1>KWIKSET</1>,< 8b>POLISHED</8b>,< 8c>BRASS</8c>
Цикл while
считывает каждую строку файла и обрабатывает ее отдельно. Затем мы хотим отобразить новую строку, где cut -d, -f1 <<< "$line"
извлекает только первое поле, поскольку оно статично, а cut -d, -f2- <<< "$line" | tr ',' '\n' | sort -n | uniq | paste -sd,
извлекает оставшиеся поля, сортирует их в числовом виде, фильтрует уникальные значения и использует paste -sd,
для воссоединения в виде запятой -список с разделителями.
вы (разделили )команда awk выглядит так
awk '(NR>1) {print "s/"p"/"$1"/g"}
{p=$1}'
что означает
{print "s/"p"/"$1"/g"}
когдаNR>1
{p=$1}
всегда "s/"p"/"$1"/g"
кавычки разбиваются (1 ):"s/" + p + "/" + $1 + "/g"
, ни p
, ни $1
не цитируются +
для конкатенации, обратите внимание, что awk использует пробел (без пробела )как неявный оператор конкатенации в первой строке выполняется только {p=$1}
.
во второй строке {print "s/"p"/"$1"/g"}
выполняется первым, и значение p
инициализируется из первой строки.
в последней строке, p
заканчиваются pfg039G
, которые отбрасываются.
Используйте точку с запятой в том же кодовом блоке, чтобы создать последовательность команд:
awk '(NR>1) {print "s/"p"/"$1"/g" ; p=$1}' test.txt
s//pfg025T/g
s/pfg025T/pfg034T/g
s/pfg034T/pfg039G/g
Теперь результат, как и ожидалось, с использованием $1
из предыдущего совпадения -в первой строке, $1
пусто.