Условный блок против условного оператора (если)

18

Скажем, у меня есть файл:

PRO 1
GLN 5.55112e-17
ILE -6.245e-17
THR 5.55112e-17

Я хочу, чтобы каждая строка, имеющая число, не равное 1, во втором столбце изменила его на 0 и оставила остаток.

Если я использую if(то есть условное утверждение), все в порядке:

awk '{if($2!=1){print $1,"0"}else{print $0}}' file
PRO 1
GLN 0
ILE 0
THR 0

Но когда я использую условный блок, происходит что-то нежелательное:

awk '$2!=1 {print $1,"0"} {print $0}' file
PRO 1
GLN 0
GLN 5.55112e-17
ILE 0
ILE -6.245e-17
THR 0
THR 5.55112e-17

Вы можете видеть, что не так.

  • Как я могу исправить эту ошибку?
  • Почему возникает эта ошибка?
  • Чем отличается условный оператор от условного блока?
Ooker
источник

Ответы:

26

В ifзаявлении, у вас есть else. Если ifне совпадает, elseветвь выполняется.

В условном выражении оба действия выполняются независимо от того, является ли условие истинным или ложным.

Простое исправление:

$ awk '$2!=1 {print $1,"0";next};{print $0}' file
PRO 1
GLN 0
ILE 0
THR 0

И вы можете сделать это более кратким:

$ awk '$2 != 1 {print $1,"0";next};1' file
PRO 1
GLN 0
ILE 0
THR 0

Если условие истинно 1и действия отсутствуют, awkповедение по умолчанию равно print. printбез аргументов будет печататься $0по умолчанию.

cuonglm
источник
4
Вы также можете сыграть в гольф awk '$2!=1?$2=0:"";1' file.
Тердон
@terdon: Хороший гольф. Я думаю, что ОП может быть трудно понять это.
Cuonglm
1
@cuonglm не могли бы вы объяснить роль next. Я предполагаю, что это подавляет второй отпечаток, если первый - правда. Что-то вроде continueв C.
Александр Цска
@ Александр Cska: nextподавляет обработку текущей строки ввода, переход к следующей. Та же роль, что whileи для всей awkпрограммы. Кроме того, awkесть своиwhile
cuonglm
10

Второй блок в

awk '$2!=1 {print $1,"0"} {print $0}' file

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

Вместо этого напишите:

awk '$2!=1 {print $1,"0"} $2==1 {print $0}' file

Или напишите:

awk '$2!=1 {print $1,"0"; next} {print $0}' file

Это приведет к пропуску безусловного блока, если сопоставлен условный блок.

Кайл Джонс
источник