#linux #unix #command-line #command
#linux #unix #командная строка #команда
Вопрос:
У меня есть текстовый файл с тысячами строк, и мне нужно повернуть строки. Вот пример:
myfile.txt
:
line1
line2
line3
line4
line5
line6
line7
Я хотел бы повернуть строки с n
шагами. Например, если n = 2
. строка 1 перемещается в строку 3, строка 2 перемещается в строку 4, строка 3 перемещается в строку 5, … строка 6 перемещается в строку 1, строка 7 перемещается в строку 2. Таким образом, результат должен быть:
line6
line7
line1
line2
line3
line4
line5
Может быть, я мог бы использовать Python и прочитать файл, повернуть список и сохранить в другой файл. Интересно, есть ли уже утилита командной строки для этой цели? он должен принимать имя файла и n
в качестве аргументов и выводить повернутые строки в новый файл.
Я ценю вашу помощь.
Комментарии:
1. Вы действительно хотите, чтобы строка 2 отображалась в результате дважды?
Ответ №1:
Используйте head
и tail
, а также некоторое простое арифметическое расширение bash. Вам также нужно либо tac
, либо wc
:
Сначала создайте минимально воспроизводимый пример для входного файла. Set n
— количество строк от конца файла для поворота к началу:
n = 2
perl -le 'print "line$_" for 1..7' > in_file
cat in_file
С принтами:
line1
line2
line3
line4
line5
line6
line7
Способ 1: Поворот с помощью tail
и head
, плюс wc
.
Это немного менее сложно, чем метод 2, и используется wc -l ... - $n
для вычисления количества строк для head
печати. Я предпочитаю этот метод, потому что намерения программиста здесь более ясны. Это также быстрее, смотрите тесты ниже.
( tail -n $n in_file ; head -n $(( $( wc -l <in_file ) - $n )) in_file ) > out_file
С принтами:
line6
line7
line1
line2
line3
line4
line5
Способ 2: поворот с помощью tail
и head
, плюс tac
.
Здесь,
tac
: запишите строки в стандартном выводе в обратном порядке,
tail -n 3
: запишите вышеуказанные строки в обратном порядке, начиная со строки 3 с конца исходного файла (таким образом, строки 1-2 не записываются), tac
: используйте tac
всего два раза, чтобы изменить обратный порядок строк, чтобы записать строки в исходном порядке.
( tail -n $n in_file ; tac in_file | tail -n $(( $n 1 )) | tac ) > out_file
Тесты:
Использование метода 1 wc
значительно быстрее, чем использование метода 2 tac
в два раза:
perl -le 'print "line$_" for 1..1e7' > in_file
n=2
for i in `seq 1 10` ; do
( time ( tail -n $n in_file ; head -n $(( $( wc -l <in_file ) - $n )) in_file ) > out_file ) 2>amp;1 | grep real
done
С принтами:
real 0m0.539s
real 0m0.538s
real 0m0.545s
real 0m0.566s
real 0m0.540s
real 0m0.532s
real 0m0.561s
real 0m0.534s
real 0m0.530s
real 0m0.520s
for i in `seq 1 10` ; do
( time ( tail -n $n in_file ; tac in_file | tail -n $(( $n 1 )) | tac ) > out_file ) 2>amp;1 | grep real
done
С принтами:
real 0m0.855s
real 0m0.884s
real 0m0.916s
real 0m0.829s
real 0m0.838s
real 0m0.873s
real 0m0.877s
real 0m0.862s
real 0m0.835s
real 0m0.867s
Я запустил это с помощью MacBook Pro с macOS v.10.14.6, запустив:
bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Ответ №2:
немного подробно с awk, но..
$ cat tst.awk
BEGIN {
step=(!step)?2:step
}
{
a[FNR step]=$0
nr=FNR
}
END {
for(i=nr 1; i in a;i )
a[(i%step) 1]=a[i]
for(i=1; i<=nr ;i )
print a[i]
}
$ awk -f tst.awk file
line6
line7
line1
line2
line3
line4
line5
$ awk -v step=4 -f tst.awk file
line4
line5
line6
line7
line1
line2
line3
Ответ №3:
Вот метод, использующий tee
команды управления заданиями wait
и amp;
и bash
замену процессов, который, в отличие от ответов до сих пор, работает с каналами и перенаправлениями, поэтому имя файла нужно указать только один раз, или вместо этого можно использовать поток:
N=2
tee >(tail -n $N amp;)
>(wait amp;amp; head -n -$N) > /dev/null < myfile.txt
Или с потоком вместо имени файла:
N=2
seq -f 'line%g' 7 |
tee >(tail -n $N amp;)
>(wait amp;amp; head -n -$N) > /dev/null
Вывод любого:
line6
line7
line1
line2
line3
line4
line5
Ответ №4:
Вы можете сделать это с помощью команд оболочки head
и tail
. Если вы хотите «повернуть» файл длиной N 2 раза, вы должны напечатать последние N-2 строки файла, а затем первые 2 строки.
Приведенный ниже пример поворачивает файл с именем «rotate» на 5 строк 2 «раза».
tail --lines 3 rotate
head --lines 2 rotate
или в виде однострочного tail --lines 3 rotate; head --lines 2 rotate
Комментарии:
1. Вы пробовали это? это не дает ожидаемого результата. Что это за жестко заданные значения
3
и2
?2. Странно, это дает мне ожидаемый результат. Какой результат вы получили? Я хотел первые 2 строки файла с 5 строками. Итак, я напечатал последние 3 строки (5-2), а затем первые 2.