Есть ли способ полностью удалить поля в awk, чтобы лишние разделители не печатали?

Рассмотрим следующую команду:

gawk -F"\t" "BEGIN{OFS=\"\t\"}{$2=$3=\"\"; print $0}" Input.tsv

Когда я устанавливаю $2 = $3 = "", предполагаемый эффект получает тот же эффект, что и запись:

print $1,$4,$5...$NF

Однако на самом деле происходит то, что я получаю два пустых поля, а дополнительные разделители полей все еще печатаются.

Можно ли фактически удалить $2 и $3?

Примечание. Если это было в Linux в bash, правильный оператор выше был бы следующим, но Windows не обрабатывает одинарные кавычки в cmd.exe.

gawk -F'\t' 'BEGIN{OFS="\t"}{$2=$3=""; print $0}' Input.tsv

Ответ 1

Это старина, но лакомство.

Как отмечает Джонатан, вы не можете удалять поля в середине, но вы можете заменить их содержимое на содержимое других полей. И вы можете сделать функцию повторного использования для обработки удаления для вас.

$ cat test.awk
function rmcol(col,     i) {
  for (i=col; i<NF; i++) {
    $i=$(i+1)
  }
  NF--
}

{
  rmcol(3)
}

1

$ printf 'one two three four\ntest red green blue\n' | awk -f test.awk
one two four
test red blue

Ответ 2

Вы не можете удалить поля в середине, но вы можете удалить поля в конце, уменьшив NF.

Итак, вы можете переместить все более поздние поля вниз, чтобы перезаписать $2 и $3, а затем уменьшить NF на два, которые стирают последние два поля:

$ echo 1 2 3 4 5 6 7 | awk '{for(i=2; i<NF-1; ++i) $i=$(i+2); NF-=2; print $0}'
1 4 5 6 7

Ответ 3

Если вы просто хотите удалить столбцы, вы можете использовать cut:

cut -f 1,4- file.txt

Чтобы подражать cut:

awk -F "\t" '{ for (i=1; i<=NF; i++) if (i != 2 && i != 3) { if (i == NF) printf $i"\n"; else printf $i"\t" } }' file.txt

Similar:

awk -F "\t" '{ delim =""; for (i=1; i<=NF; i++) if (i != 2 && i != 3) { printf delim $i; delim = "\t"; } printf "\n" }' file.txt

НТН

Ответ 4

Одним из способов может быть удаление полей, подобных используемым, и удаление дополнительных пробелов с помощью gsub:

awk 'BEGIN { FS = "\t" } { $2 = $3 = ""; gsub( /\s+/, "\t" ); print }' input-file

Ответ 5

В дополнение к ответу Suicidal Steve я хотел бы предложить еще одно решение, но с помощью sed вместо awk.

Это кажется более сложным, чем использование разреза, как это предложил Стив. Но это было лучшее решение, потому что sed -i позволяет редактировать на месте.

sed -i 's/\(.*,\).*,.*,\(.*\)/\1\2/' FILENAME

Ответ 6

Единственный способ, с помощью которого я могу сделать это в Awk без использования цикла, - использовать gsub on $0 для объединения соседних FS:

$ echo {1..10} | awk '{$2=$3=""; gsub(FS"+",FS); print}'
1 4 5 6 7 8 9 10

Ответ 7

Хорошо, если целью является удаление дополнительных разделителей, вы можете использовать "tr" в Linux. Пример:

$echo "1,2,, 5" | tr -s ','

1,2,5

Ответ 8

echo one two three four five six|awk '{
print $0
is3=$3
$3=""
print $0
print is3
}'

один два три четыре пять шесть

один два четыре пять шесть

три