awk повторяет строки слишком много раз

Я использую awk для создания файла, который содержит строки текста и использует входной файл чисел. Я хочу заменить каждым числом однажды, т.е. строка 1 получает первое число, строка 2 получает второе число, строка 3 получает третье число. Однако каждой строке присваивают, первый номер, сопровождаемый каждой строкой, присвоил второй номер и т.д...

Вот мой входной файл текста (test.awk):

{printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}"); 
}

это - входной файл чисел:

-0.00432739
0.41369093
0.00000000

команда: awk -f test.awk < input.txt > new.txt

производит это, где эти 3 строки повторяются 3 раза:

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1; h=0;}

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1; h=0;}

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

то, что я хочу, является этим:

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

Кто-либо может сказать мне, как мешать ему присвоить каждое число каждой строке и затем повторить эти 3 строки?

2
задан 6 September 2015 в 16:10

4 ответа

Использование модуля 3 (%) и небольшая коррекция в printf(\"%%f %%s\n\",$1=="$1",$2)

{
  if (NR%3==1) {printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%3==2) {printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%3==0) {printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")}
}

Модуль также является хорошей идеей, если в вашем input.txt более трех строк. Число 3 в приведенном выше коде зависит от строк printf в test.awk. С четырьмя printf строками вам нужно что-то вроде этого:

{
  if (NR%4==1) {printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%4==2) {printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%4==3) {printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")};
  if (NR%4==0) {printf("\n($2 == \"foo.bar\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")}
}

Вывести с тремя строками в input.txt:

% awk -f test.awk input.txt

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

Вывод с более трех строк в input.txt

% awk -f test.awk input.txt

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}
($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}
2
ответ дан 2 December 2019 в 02:21

Можно использовать после кода awk (test.awk):

BEGIN{count=0}{count++}{if(count==1){printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1;}");
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1;}");
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1; h=0;}"); }}
1
ответ дан 2 December 2019 в 02:21

Джанет, тебе нужно сообщить awk, что после применения первой строки кода к первой строке ввода следует перейти к следующей строке ввода. И затем, после применения второй строки кода, он должен перейти к следующей строке ввода и так далее. В противном случае awk применяет каждую строку кода к каждой строке ввода. Самый простой способ сделать это - вставить команду getline после каждой строки кода (кроме последней, где она бесполезна):

[alessandro@localhost ~]$ cat /tmp/a.awk
{printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
getline
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
getline
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}"); 
}
[alessandro@localhost ~]$ cat /tmp/a.txt
-0.00432739
0.41369093
0.00000000
[alessandro@localhost ~]$ awk -f /tmp/a.awk /tmp/a.txt
($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}[alessandro@localhost ~]$ 
0
ответ дан 2 December 2019 в 02:21

Я просто сохранил бы числа в массиве и использовании это. Во-первых, измените Ваш test.awk так, чтобы это было похоже на это:

($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;} 

Можно сделать это автоматически с этой командой:

sed -i 's/^{//;s/}$//;s/printf("\\n//;s/");//' test.awk 

После того как это сделано, можно использовать этот сценарий для получения вывода:

$ awk 'NR==FNR{a[NR]=$1; next}{gsub(/"\$1"/,a[FNR]); print}' input.txt test.awk 
($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1==-0.00432739,$2); a=1;} 
($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.41369093,$2); a=1;} 
($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.00000000,$2); a=1; h=0;} 

Объяснение

NR текущий номер строки и FNR текущий номер строки текущего файла. Так, эти два равны только, когда 1-й файл читается. Поэтому первая часть awk сценарий выше (NR==FNR{a[NR]=$1; next}) создает массив, ключи которого являются номерами строки input.txt файл и чьи значения являются соответствующими числами. Это затем работает next перемещаться в следующую строку, не выполняя вторую часть сценария.

Вторая часть заменит строкой "$1" со значением, сохраненным в массиве a для текущего номера строки второго файла (FNR). Результат - то, что Вы попросили.


Другой подход должен был бы использовать некоторый обман. Вместо того, чтобы использовать сценарий для этого, использовать paste присоединиться к файлам и awk сделать замену. Сначала измените test.awk как описано выше, и затем:

$ paste input.txt test.awk | awk '{gsub(/"\$1"/,$1);$1="";print;}'
 ($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1==-0.00432739,$2); a=1;}
 ($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.41369093,$2); a=1;}
 ($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.00000000,$2); a=1; h=0;}

Объяснение

paste команда распечатает каждую строку своих входных файлов вместе. Так, с входом выше, это распечатает:

$ paste input.txt test.awk
-0.00432739 ($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
0.41369093  ($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
0.00000000  ($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;} 

Это затем передается через awk сценарий который

  • Использование gsub заменять все случаи "$1" со значением $1 (gsub(/"\$1"/,$1););
  • После того как это сделано, $1 набор должен опустеть ($1="") так, чтобы число из первого файла не было распечатано в начале строки.
  • Наконец, это печатает получающуюся строку (print).
1
ответ дан 2 December 2019 в 02:21

Другие вопросы по тегам:

Похожие вопросы: