У мене є файл foo.txt
, що містить такі рядки:
a
b
c
Я хочу просту команду, яка призводить до вмісту foo.txt
буття:
a
b
У мене є файл foo.txt
, що містить такі рядки:
a
b
c
Я хочу просту команду, яка призводить до вмісту foo.txt
буття:
a
b
Відповіді:
Використання GNU sed
:
sed -i '$ d' foo.txt
-i
Варіант не існує в GNU sed
версіях старше 3.95, так що ви повинні використовувати його в якості фільтра з тимчасовим файлом:
cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
Звичайно, у такому випадку ви можете також використовувати head -n -1
замість цього sed
.
MacOS:
Для Mac OS X (станом на 10.7.4) еквівалент sed -i
команди, наведеної вище
sed -i '' -e '$ d' foo.txt
$ d
є регулярним виразом. Це команда sed. d
є командою для видалення рядка, тоді як $
означає "останній рядок у файлі". Коли вказується місце розташування (яке називається "діапазон" в sed lingo) перед командою, ця команда застосовується лише до вказаного місця. Отже, ця команда прямо говорить «видаліть її в діапазоні останнього рядка у файлі». Досить стрункий і прямо до точки, якщо ви запитаєте мене.
Це, безумовно, найшвидше і найпростіше рішення, особливо на великих файлах:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
якщо ви хочете видалити верхній рядок, скористайтеся цим:
tail -n +2 foo.txt
що означає вихідні лінії, починаючи з другого рядка.
Не використовуйте sed
для видалення рядків зверху або внизу файлу - це дуже повільно, якщо файл великий.
head -n -1 foo.txt
достатньо
brew install coreutils
(основні утиліти GNU) та використовувати ghead
замість них head
.
FILE=$1; TAIL=$2; head -n -${TAIL} ${FILE} > temp ; mv temp ${FILE}
Запустіть його для видалення 4 рядків, наприклад, з myfile як: ./TAILfixer myfile 4
звичайно, спочатку зробіть його виконуванимchmod +x TAILfixer
sed
, ця команда також досить повільна
У мене виникли проблеми з усіма відповідями тут, оскільки я працював з ВЕЛИЧЕЗНИМ файлом (~ 300Gb), і жодне з рішень не масштабувало. Ось моє рішення:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
Словом: Дізнайтеся довжину файлу, який ви хочете в кінцевому підсумку (довжина файлу мінус довжина його останнього рядка, використовуючи bc
), і встановіть, що це місце є кінцем файлу (за допомогою dd
одного байта /dev/null
на це).
Це швидко, тому що він tail
починає читати з кінця і dd
замінить файл на місці, а не копіює (і розбирає) кожен рядок файлу, що і роблять інші рішення.
ПРИМІТКА. Це видаляє рядок з файлу на місці! Зробіть резервну копію чи тест на фіктивний файл, перш ніж випробувати його на власному файлі!
Щоб видалити останній рядок із файлу, не читаючи весь файл чи нічого не переписуючи , можна скористатися
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Щоб видалити останній рядок, а також надрукувати його на stdout ("поп"), ви можете комбінувати цю команду з tee
:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Ці команди можуть ефективно обробляти дуже великий файл. Це схоже на натхнення і відповідь Йоссі, але вона уникає використання кількох додаткових функцій.
Якщо ви збираєтесь використовувати ці неодноразово і хочете поправити помилки та деякі інші функції, ви можете скористатися poptail
командою тут:
https://github.com/donm/evenmoreutils
truncate
недоступна в OS X за замовчуванням. Але це легко встановити за допомогою Brew : brew install truncate
.
Користувачі Mac
якщо ви хочете лише видалити останній рядок виводу, не змінюючи сам файл
sed -e '$ d' foo.txt
якщо ви хочете видалити останній рядок вхідного файлу, зробіть це
sed -i '' -e '$ d' foo.txt
-i ''
повідомляє sed змінювати файл на місці, зберігаючи резервну копію у файлі з розширенням, поданим як параметр. Оскільки параметр є порожнім рядком, файл резервного копіювання не створюється. -e
каже sed виконувати команду. Команда $ d
означає: знайдіть останній рядок ( $
) та видаліть його ( d
).
На Mac, голова -n -1 не працює. І я намагався знайти просте рішення [не турбуючись про час обробки], щоб вирішити цю проблему лише за допомогою команд «голова» та / або «хвіст».
Я спробував наступну послідовність команд і був радий, що міг вирішити це просто за допомогою команди "хвіст" [з параметрами, доступними на Mac]. Отже, якщо ви перебуваєте на Mac і хочете використовувати лише "хвіст" для вирішення цієї проблеми, ви можете використовувати цю команду:
cat file.txt | хвіст -р | хвіст -n +2 | хвіст -р
1> хвіст -r: просто повертає порядок рядків у своєму введенні
2> хвіст -n +2: це друкує всі рядки, починаючи з другого рядка на вводі
ghead -n -1
awk 'NR>1{print buf}{buf = $0}'
По суті, цей код говорить наступне:
Для кожного рядка після першого надрукуйте буферну лінію
для кожного рядка скиньте буфер
Буфер розміщений на один рядок, отже, ви закінчуєте друковані лінії 1 до n-1
awk "NR != `wc -l < text.file`" text.file |> text.file
Цей фрагмент робить трюк.
Обидва ці рішення є тут в інших формах. Я вважав це трохи більш практичним, зрозумілим та корисним:
Використання dd:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}
Використання усікання:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
Ось як це можна зробити вручну (я особисто дуже багато використовую цей метод, коли мені потрібно швидко видалити останній рядок у файлі):
vim + [FILE]
Цей +
знак означає, що коли файл відкриється в текстовому редакторі vim, курсор буде розміщений в останньому рядку файла.
Тепер просто натисніть d
двічі на клавіатурі. Це зробить саме те, що ви хочете - видаліть останній рядок. Після цього натисніть, :
а потім - x
і натисніть Enter
. Це вбереже зміни та поверне вас до оболонки. Тепер останній рядок успішно видалено.
sed -i
команди, наведеної вище, єsed -i '' -e '$ d' foo.txt
. Такожhead -n -1
наразі не працює на Mac.