Як видалити останній стовпець файлу в Linux


25

Я хочу видалити останній стовпець файлу txt, поки я не знаю, що таке номер стовпця. Як я міг це зробити?

Приклад:

Вхід:

1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222

І я хочу, щоб результат був таким:

1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

Існує багато способів зробити це. Попросіть додати приклад і очікуваний вихід з нього ..
heemayl

@heemayl нормально, що я зробив
zara

Дякую .. чи розділена вкладка стовпців чи розділений пробіл?
heemayl

@heemayl простір deliminator
Зара

Відповіді:


43

З awk:

awk 'NF{NF-=1};1' <in >out

або:

awk 'NF{NF--};1' <in >out

або:

awk 'NF{--NF};1' <in >out

Хоча це схоже на вуду, воно працює. Кожній з цих команд awk є три частини.

Перше - NFце передумова другої частини. NF- змінна, що містить кількість полів у рядку. У AWK все є істинним, якщо вони не дорівнюють 0 або порожній рядок "". Отже, друга частина (де NFзменшена) відбувається лише тоді, коли NFвона не дорівнює 0.

Друга частина (або NF-=1 NF--або --NF) просто віднімає одну зі NFзмінної. Це запобігає друкуванню останнього поля, оскільки коли ви змінюєте поле (видаляючи в цьому випадку останнє поле), awkпереконструюйте $0, об'єднуйте всі поля, розділені пробілом за замовчуванням. $0більше не містило останнього поля.

Заключна частина - 1. Це не магічно, він просто використовується як вираз, що означає true. Якщо awkвираз оцінюється як істинне без будь-яких пов’язаних дій, awkдія за замовчуванням є print $0.


@JJoao: А, дякую, забув про --. Примітка на даний момент вам потрібна ;1для сумісності з POSIX.
cuonglm

Мій початковий інстинкт полягав би в тому, щоб використовувати петлю, але це набагато більш стисло і розумно.
Сергій Колодяжний

5
Варто зазначити, що якщо ви використовуєте роздільник, який не використовується за замовчуванням, вам потрібно буде внести деякі зміни. Припустимо, що ,це ваш роздільник:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
Містер Лама

1
Ефект декрементування NF - це невизначена поведінка POSIX - ви отримаєте різний вихід залежно від того, який awk ви виконуєте. Деякі букси видалять останнє поле, як вам захочеться, деякі взагалі нічого не робитимуть, а інші можуть повідомити про синтаксичну помилку чи щось інше.
Ед Мортон

16

Використання grepз PCRE:

$ grep -Po '.*(?=\s+[^\s]+$)' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

Використання GNU sed:

$ sed -r 's/(.*)\s+[^\s]+$/\1/' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

1
@ramin Sure..можливо, будь ласка, задайте це як нове запитання (ось як працює цей сайт) :)
heemayl

@ramin Чи дає вам обмеження у часі чи якесь попередження?
heemayl

це говорить, що це не в стандартному питанні!
zara

@ramin Добре ... будь-ласка, зв'яжіться з адміністратором, можливо, вони можуть допомогти вам у цьому. є можливість, що на питання вже задають і відповідають ..
heemayl

3
Не задавайте надзвичайно основних питань, таких як " як я можу перейменувати ім'я файлу в Linux ". Використовуйте Google.
Крістоффер Хаммарстрем

11

Використання Perl:

perl -lane '$,=" ";pop(@F);print(@F)' in

Використання rev+ cut:

rev in | cut -d ' ' -f 2- | rev

5

Використання GNU sed:

sed -r 's/\s+\S+$//' input.txt

Загалом, цей працює з BSD sed в OSX, а також GNU sed:

sed 's/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//' input.txt

1

Якщо роздільник є завжди одним знаком (тому два чи більше послідовних роздільників позначають порожні поля), ви можете headлише перший рядок із вхідного файлу, порахувати роздільники ( nроздільник означає кількість полів n+1), а потім використовувати cutдля друку з першого 1поля до nпершого поля (друге до останнього), наприклад, із вкладеним вкладкою:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l)
cut -f1-$n infile > outfile

або, наприклад, з файлом csv :

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l)
cut -d, -f1-$n infile > outfile

Пізніше я запустити деякі орієнтири, якщо у мене буде час, але з величезним вкладом я думаю, що це рішення повинно бути швидшим, ніж інші рішення, які використовують регулярний вираз, оскільки цей процес виконує мінімальну обробку на першому рядку, щоб отримати "ні". полів, а потім використовує, cutяке оптимізоване для цієї роботи.


1

Портативно ви можете використовувати будь-яке з цих:

sed 's/[[:space:]]*[^[:space:]]*$//' file

awk '{sub(/[[:space:]]*[^[:space:]]*$/,"")}1' file

0

Використання vim:

Відкрити файл у vim

vim <filename> 

Перейдіть до першого ряду, на випадок, якщо курсор розміщений де-небудь ще.

gg

Створіть макрос з назвою "q" qq, який переходить на задню частину поточного рядка $, потім повернеться до останнього пробілу F( велика літера F, а потім буквальний пробіл), потім видаліть з поточного положення через кінець рядка, Dспустіться до наступного рядка jта зупинити макро запис із q.

qq$F Djq

Тепер ми можемо повторити наш макрос @qдля кожного рядка.
Ми також можемо натиснути, @@щоб повторити останній макрос або ще простіше:

99@q

повторити макрос 99 разів.
Примітка. Номер не повинен точно відповідати рядкам.


0

Для людей, які мають подібну проблему, але з різними роздільниками поля, цей awkспосіб правильно збереже роздільник поля:

$ cat file 
foo.bar.baz
baz.bar.foo
$ awk -F'.' 'sub(FS $NF,x)' file
foo.bar
baz.bar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.