2012-05-21 2 views
10

Рассмотрим следующую команду:Есть ли способ полностью удалить поля в 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 
+2

Вы должны использовать одиночные кавычки для внешнего набора, то вам не придется бежать двойные кавычки внутри сценария. Если вы используете двойные кавычки для внешнего набора, чтобы вы могли вставлять переменные оболочки, вместо этого используйте '-v', чтобы вместо этого выполнить переменную. –

+0

Я использую awk в Windows. По какой-то причине Cmd.exe плохо работает с одинарными кавычками. – merlin2011

+0

Я сделал это еще 10 лет назад (думаю). попробуйте сделать $ 2 = $ 3 = ""; $ 0 = $ 0'. Удачи. – shellter

ответ

4

Это старичок, но Гуди.

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

$ 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 
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

Похожие:

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

НТН

+0

В последнем примере печатается заключительная вкладка. '{for (...) {printf delim $ i; delim = "\ t"}; printf "\ n"} ' –

+0

Я беспокоюсь о gsub, потому что есть другие поля, которые законно пусты, и я хочу, чтобы множественные разделители. – merlin2011

+0

@DennisWilliamson Спасибо за исправления. – Steve

7

Вы не можете удалять поля в середине, но вы можете удалить поля в конце концов, путем уменьшения 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 
1

Одним из способов может быть, чтобы удалить поля, как вы делаете, и удалить дополнительные пространства с gsub:

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

в дополнение ответа суицидальными Стива я хотел бы предложить еще одно решение, но с использованием СЭД вместо AWK.

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

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

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

$ echo {1..10} | awk '{$2=$3=""; gsub(FS"+",FS); print}' 
1 4 5 6 7 8 9 10 
-1
echo one two three four five six|awk '{ 
print $0 
is3=$3 
$3="" 
print $0 
print is3 
}' 

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

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

три

0

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

$ echo "1,2 ,,, 5" | тр -s «»

1,2,5