Я использую 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 строки?
Использование модуля 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;}
Можно использовать после кода 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;}"); }}
Джанет, тебе нужно сообщить 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 ~]$
Я просто сохранил бы числа в массиве и использовании это. Во-первых, измените Ваш 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
).