#linux #bash #shell #awk
#linux #удар #оболочка #awk #bash
Вопрос:
У меня есть файл с несколькими строками, и я хочу непрерывно выводить некоторые строки файла, например, в первый раз печатать со строки 1 по строку 5, в следующий раз печатать со строки 2 по строку 6 и так далее. Я считаю AWK очень полезной функцией, и я попытался написать код самостоятельно, но он просто ничего не выводит. Ниже приведен мой код
#!/bin/bash
for n in `seq 1 3`
do
N1=$n
N2=$((n 4))
awk -v n1="$N1" -v n2="$N2" 'NR == n1, NR == n2 {print $0}' my_file >> new_file
done
Например, у меня есть входной файл с именем my_file
1 99 tut
2 24 bcc
3 32 los
4 33 rts
5 642 pac
6 23 caas
7 231 cdos
8 1 caee
9 78 cdsa
Затем я ожидаю, что выходной файл в виде
1 99 tut
2 24 bcc
3 32 los
4 33 rts
5 642 pac
2 24 bcc
3 32 los
4 33 rts
5 642 pac
6 23 caas
3 32 los
4 33 rts
5 642 pac
6 23 caas
7 231 cdos
Комментарии:
1. Спасибо, что продемонстрировали свои усилия в виде кода. ИМХО, вы могли бы сделать это в одном
awk
самом. Не могли бы вы, пожалуйста, опубликовать образец вашего ввода и ожидаемого результата для лучшего понимания вопроса здесь, мы могли бы сделать это в одномawk
(если возможно) тоже.2. Привет @RavinderSingh13 Я просто редактирую это, надеюсь, теперь это понятнее. Спасибо.
3. Я попробовал ваш код, и вывод в
new_file
выглядит правильным.4. @Barmar Я перешел на другой компьютер, и теперь мой код тоже работает. Спасибо за ваш комментарий, это напоминает мне, что проблема может быть связана с системой.
Ответ №1:
Не могли бы вы, пожалуйста, попробовать следующее, написанное и протестированное с показанными примерами в GNU awk
. Где нужно указать все строки, которые необходимо напечатать в lines_from
переменной, тогда есть переменная с именем till_lines
, которая сообщает нам, сколько строк нам нужно напечатать из определенной строки (например,—> из 1-й строки также напечатать следующие 4 строки). С другой стороны, я протестировал код OP, и он отлично сработал для меня, он генерирует выходной файл с помощью new_file, поскольку вызов awk
в цикле bash НЕ является хорошей практикой, поэтому добавляю это в качестве улучшения и здесь.
awk -v lines_from="1,2,3" -v till_lines="4" '
BEGIN{
num=split(lines_from,arr,",")
for(i=1;i<=num;i ){ line[arr[i]] }
}
FNR==NR{
value[FNR]=$0
next
}
(FNR in line){
print value[FNR] > "output_file"
j=""
while( j<=till_lines){ print value[FNR j] > "output_file" }
}
' Input_file Input_file
Когда я вижу содержимое output_file
, я вижу следующее:
cat output_file
1 99 tut
2 24 bcc
3 32 los
4 33 rts
5 642 pac
2 24 bcc
3 32 los
4 33 rts
5 642 pac
6 23 caas
3 32 los
4 33 rts
5 642 pac
6 23 caas
7 231 cdos
Объяснение: Добавляю подробное объяснение выше.
awk -v lines_from="1,2,3" -v till_lines="4" ' ##Starting awk program from here and creating 2 variables lines_from and till_lines here, where lines_from will have all line numbers which one wants to print from. till_lines is the value till lines one has to print.
BEGIN{ ##Starting BEGIN section of this program from here.
num=split(lines_from,arr,",") ##Splitting lines_from into arr with delimiter of , here.
for(i=1;i<=num;i ){ ##Running a for loop from i=1 to till value of num here.
line[arr[i]] ##Creating array line with index of value of array arr with index of i here.
}
}
FNR==NR{ ##Checking condition FNR==NR which will be TRUE when 1st time Input_file is being read.
value[FNR]=$0 ##Creating value with index as FNR and its value is current line.
next ##next will skip all further statements from here.
}
(FNR in line){ ##Checking condition if current line number is coming in array then do following.
print value[FNR] > "output_file" ##Printing value with index of FNR into output_file
j="" ##Nullifying value of j here.
while( j<=till_lines){ ##Running while loop from j=1 to till value of till_lines here.
print value[FNR j] > "output_file" ##Printing value of array value with index of FNR j and print output into output_file
}
}
' Input_file Input_file ##Mentioning Input_file names here.
Комментарии:
1. @RavinderSingh13 Спасибо за ваши усилия, я решил свою проблему, перейдя на другой компьютер, похоже, что виновата система. Ваш сценарий и комментарии очень познавательны, спасибо.
2. @witt. S, ваше приветствие, ИМХО хотел бы поставить здесь точку. Честно говоря, вам следует избегать использования
for
цикла и последующего вызоваawk
внутри него. Вызовawk
на каждой итерации цикла for является излишним, ИМХО, если возможно, вы могли бы использовать это единственное решение. приветствия.
Ответ №2:
Другой awk
вариант
awk '
BEGIN {N1=1; N2=5}
arr[NR]=$0 {}
END {
while (arr[N2]) {
for (i=N1; i<=N2; i )
print arr[i]
N1
N2
}
}
' file