удаление первого и последнего символа каждой строки из командной строки

8

Я пытаюсь удалить первый и последний символы каждой строки в текстовом файле и сохранить полученную усеченную версию в новом файле. Кто-нибудь есть идеи о том, как сделать это эффективно с помощью awkили других программ / команд Linux, специально для больших файлов?

input.txt

(s,2,4,5,6)
"s,1,5,5,2"
{z,0,4,5,3}
[y,2,4,5,5]
(y,4,4,5,7)
(r,20,4,5,7)
(e,9,4,5,2)

Ожидаемый output.txt

s,2,4,5,6
s,1,5,5,2
z,0,4,5,3
y,2,4,5,5
y,4,4,5,79
r,20,4,5,7
e,9,4,5,2
pacodelumberg
источник

Ответы:

14

Другой способ только для этого:

rev input | cut -c2- | rev | cut -c2-

(Примечание: в GNU cutон работает только для символов, состоящих только из одного байта (как в вашем примере)).

Дрейк Кларрис
источник
Ницца! Это значительно быстрее, чем решения sed и awk, предложенные до сих пор.
Жиль "ТАК - перестань быть злым"
Я предложил этот ответ для людей, которые боятся синтаксиса sed / awk / regex, но не предполагали, что он быстрее, особенно для больших файлов, с тремя каналами и передачей всего содержимого через каждый. Можно было бы подумать, что sed или awk читает строку за раз, будет более эффективным для больших файлов.
Дрейк Кларрис
3
Думаю, это то, что за 40 с лишним лет оптимизации многих из этих * nix утилит принесет вам!
Дрейк Кларрис
@ Жиль, GNU sed быстрее в некоторых локалях utf8 для некоторых форм ввода, и это зависит от того, рассматриваете ли вы время настенных часов или процессорное время. ssedили набор инструментов из семейной реликвии sedможет обеспечить лучшую производительность.
Стефан Шазелас
@ Жиль Theres нет записи MAN для rev в Solaris 5.10. Я закончил тем, что использовалsed
ayrton_senna
10

По вашему вопросу удалите последнее и первое слово из входного файла, как показано ниже:

sed 's/.$//; s/^.//' inputfile
Рахул Патил
источник
Было бы здорово, если бы вы могли сравнить их с другим решением s/.\(.*\).$/\1/. Это может быть быстрее из-за неиспользования обратных ссылок, и в вопросе упоминались «большие файлы».
2010 года
4
@ l0b0 Я проверял с time yes | head -n 10000000 | COMMAND >/dev/null. Я получаю rev input | cut -c2- | rev | cut -c2-→ 0,14 с, sed 's,.\(.*\).$,\1,'→ 3,38 с; awk '{print substr($0,2,length()-2);}'→ 3,50 с; sed 's/.$//; s/^.//'→ 5.09с.
Жиль "ТАК - перестань быть злым"
@ Жиль +1 Это должен быть ответ.
10
2
@ Жиль, это очень короткие строки. Я считаю, что для строк шириной 30 символов решение @ RahulPatil в 3 раза быстрее с GNU sed, чем решение @ juampa. Также. sed 's/.\(.*\)./\1/'кажется быстрее, чем sed 's/^.\(.*\).$/\1/'(GNU sed снова). Кроме того, производительность зависит от локали (интерпретация того, что символ) и от sedреализации (в этом отношении sed из набора инструментов семейной реликвии значительно быстрее, чем GNU sed).
Стефан Шазелас
5

Есть много возможностей, как всегда

sed 's,.\(.*\).$,\1,g' your_file

объяснение

  • , - разделитель sed может быть любым другим символом, если его экранировать там, где это необходимо.
  • . Совпадение с одним персонажем
  • \(.*\) - Сгруппируйте оставшуюся часть, и она сохраняется для последующего извлечения.
  • . Снова сопоставьте один символ
  • $ - Конец линии
  • \1 - вывести текст, соответствующий группе выше
  • g заменить глобально на линии.
jpmuc
источник
2
Почему g? в каждой строке будет только один матч.
njsg
Обратите внимание, что он не удалит ничего из строк, содержащих менее 2 символов.
Стефан Шазелас
3

Вы также можете сделать это, awkесли вы предпочитаете

awk '{print substr($0,2,length()-2);}' input.txt > output.txt
StrongBad
источник
2
tr -d '()[]{}"' < your_file

Это должно работать так же. Он хорошо «переводит» каждый из символов в ничто (удаляет).

Недостатком является то, что он удалит их, если они не будут первым / последним символом. Он также пропустит любые символы окончания, которые вы не перечислили в ()[....

Марк Николс
источник