Как я могу редактировать последние n строк в файле?

10

Есть ли команда, которая позволит мне редактировать последние n строк в файле? У меня есть несколько файлов, которые все имеют различное количество строк внутри. Но я хотел бы изменить последние n строк в каждом файле. Цель состоит в том, чтобы заменить запятые точкой с запятой в последних n строках. Но только в самых последних n строках.

Я не хочу удалять какие-либо строки, я просто хочу заменить каждую запятую точкой с запятой в последних n строках в каждом файле.

Используя команду sed, я могу заменить самую последнюю строку этой командой. Как описано здесь: Как я могу удалить текст в последней строке файла?

Но это только позволяет мне изменить самую последнюю строку, а не последние n строк.

sku2003
источник
1
Просто используя sed '24,$s/,/:/g' filename где 24стартовая линия`
Валентин Байрами

Ответы:

13

Заменить запятые на точку с запятой в последних n строках ed:

n=3
ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq'

Разделив это на части:

  • ed -s = запустить ed без вывода сообщений (не сообщайте о байтах, написанных в конце)
  • '$-'= с конца файла ( $) минус ...
  • $((n-1)) = n-1 строк ...
  • ( $' ... '= процитировать оставшуюся часть команды, чтобы защитить ее от оболочки)
  • ,$s/,/;/g= ... до конца файла ( ,$), найдите и замените все запятые точкой с запятой.
  • \nwq = завершить предыдущую команду, затем сохранить и выйти

Заменить запятые на точку с запятой в последних n строках sed:

n=3
sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input

Разбивая это на части:

  • -i = редактировать файл "на месте"
  • $(( ... )) = сделать немного математики:
  • $( wc -l < input) = получить количество строк в файле
  • -n + 1 = идти назад n-1 строк
  • ,\$ = от n-1 строк до конца файла:
  • s/,/;/g = заменить запятые точкой с запятой.
Джефф Шаллер
источник
Можно заменить wc -l < inputна wc -l input. Должно быть быстрее на несколько наносекунд :)
садовник
1
за исключением того, что wc -l inputвыводит также и имя файла; нам нужен только счетчик строк
Джефф Шаллер
Первый совет с Эд хорош и прост.
sku2003
Я фактически закончил тем, что получил помощь от совершенно другой стороны. В результате получился странный кусок кода, который добился цели, но был длинным и странным. Я предполагаю, что это некоторые из странных вещей, с которыми вы можете столкнуться, когда собираете решение. В любом случае, ваш код красивее, короче и менее сложен, чем мой. Код здесь также работал:
sku2003
кошка input.file | sed 's /, /, \ n / g' | sed -n '1! G; h; $ p' | awk -vn = 2 'NR <= n {gsub (",", ";", $ 0)} {print}' | sed -n '1! G; h; $ p' | sed '/ ^ \ s * $ / d'> output.file
sku2003
6

Решение с использованием tac и sed для замены каждой запятой на точку с запятой в последних 50 строках файла file.txt:

tac file.txt | sed '1,50s/,/;/g' | tac
Gohu
источник
5

С GNU headи Bourne-подобной оболочкой:

n=20
{ head -n -"$n"; tr , ';'; } < file 1<> file

Мы перезаписываем файл поверх себя. Это нормально здесь транслитерации байт в байт , но не обязательно , если изменение влечет за собой изменение размера файла (в этом случае, вы хотите заменить 1<> fileс > other-file && mv other-file file, например).

Стефан Шазелас
источник
1
Вот документы1<> , с которыми я был незнаком. Кроме того, spongeиз moreutils - хороший инструмент для конвейеров, где вы хотите перезаписать свой ввод.
Майлз
1

Предположим, мы хотим заменить последние 7строки следующей последовательности сценарием оболочки и реализацией GNU sed:

$ seq 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Шаг 1 : позволяет получить номер последней строки последовательности, как показано ниже. Взгляните на то и это :

$ lastLine=`seq 20|sed -n '$='`

$ echo $lastLine 
20

Шаг 2 : давайте установим количество строк (в конце последовательности), которые мы намереваемся редактировать:

$ numberOfLines=7

$ echo $numberOfLines 
7

Шаг 3 : давайте посчитаем начальную строку на основе предыдущих переменных, как показано ниже. Посмотрите на это :

$ startLine=`expr $lastLine - $numberOfLines + 1`

$ echo $startLine 
14

Шаг 4 : Теперь мы можем заменить последние 7 строк последовательности чем-то другим, как показано ниже. Посмотрите на это :

$ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}"
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

Шаг 4 использует раздел 4.4 man-страницы sed, в котором говорится:

'ADDR1,+N'
     Matches ADDR1 and the N lines following ADDR1.

Шаг 4 также использует двойные кавычки, как упомянуто здесь .


Что ж, 4 шага не нужны, если мы используем ответ Гоху так:

$ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0
user3405291
источник
0

Использование tailи труба для седа:

tail -n 20 file | sed 's/,/;/g'

Это работает с файлом за последние 20 строк. Если вы хотите, чтобы ваши файлы направлялись прямо в файл, используйте:

tail -n 20 file | sed -i 's/,/;/g'

Джон Гуфи
источник