У мене є файл 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.