Використовуйте простір як роздільник з командою cut


328

Я хочу використовувати простір як роздільник з cutкомандою.

Який синтаксис я можу використовувати для цього?


42
неправда, сторінка man для вирізання цього не пояснює, і взагалі
малоінформативна

2
Також "розрізання інформації" в цьому випадку не є поліпшенням.
Космос Кардіфф людина

3
@ mklement0, якщо я пам'ятаю, я відповідав на коментар, який з тих пір був видалений, який відхилив це запитання як відповідь на чоловічій сторінці, яка, на мою думку, була "неправдою", незалежно від того, чи є для цього вагома причина. чи ні - зараз, хоча я визнаю, що може бути вагома причина цієї нестачі інформації, я все ще думаю, що документація без загальних прикладів використання часто є, щонайменше, дратує, коли не відверто марно
UncleZeiv

3
@UncleZeiv Зрозумів; дякую за уточнення; враховуючи інтерес до цього питання, справедливо припустити, що manсторінки недостатньо. Давайте подивимось: " -d delimВикористовувати delimяк символ роздільника поля замість символу вкладки." (BSD cut, але версія GNU та специфікація POSIX майже однаково). Використання оболонки для виклику cut- типовий випадок - тому вимагає, щоб ви знали, як взагалі передавати простір як аргумент, використовуючи синтаксис оболонки , що, певно, не є завданням cutчоловічої сторінки. Однак приклади в реальному світі завжди допомагають, а сторінка GNU їх не вистачає.
mklement0

4
хоча обрана відповідь технічно правильна, розгляньте вибір новітньої та вичерпнішої відповіді за допомогою @ mklement0 як канонічну відповідь, щоб вона фільтрувалася доверху.
David LeBauer

Відповіді:


367
cut -d ' ' -f 2

Де 2 - номер поля потрібного вам пробілу.


2
Ви можете сказати cut використовувати будь-яку кількість певного символу як роздільника, як у RegEx? наприклад, будь-яка кількість пробілів, наприклад, \ s +
амфібій

3
@foampile Ні, я не вірю, що ви можете.
Джонатан Хартлі

6
Ви не можете використовувати регулярні вирази cut, але ви можете cutsнамагатися "виправити" всі cutобмеження: github.com/arielf/cuts
arielf

ви можете отримати кожне третє поле, обмежене пробілом? як, cut -d ' ' -f 3,6,9,12,15,18не вказуючи кожне число?
Моносіто

169

Зазвичай, якщо ви використовуєте простір як роздільник, ви хочете розглядати кілька пробілів як одне ціле, тому що ви аналізуєте вихід команди, вирівнюючи деякі стовпці з пробілами. (і пошук Google, що веде мене сюди)

У цьому випадку однієї cutкоманди недостатньо, і вам потрібно використовувати:

tr -s ' ' | cut -d ' ' -f 2

Або

awk '{print $2}'

2
Дякуємо за використання прикладного прикладу, просто того, що мені було потрібно.
spazm

44

Доповнити існуючі корисні відповіді; наконечник капелюха до QZ Підтримка за те, щоб заохотити мене опублікувати окрему відповідь:

Тут грають два чіткі механізми :

  • (А) є чи cut сам по собі вимагає роздільник (простору, в даному випадку) передається -dможливості бути окремим аргументом або чи є це прийнятно , щоб додати його безпосередньо до -d.

  • (b) як оболонка зазвичай аналізує аргументи, перш ніж передавати їх команді, що викликається.

(а) відповідає цитатою з керівних принципів POSIX щодо комунальних послуг (моє значення)

Якщо SYNOPSIS стандартної утиліти показує параметр із обов'язковим параметром-аргументом [...], відповідна програма використовує окремі аргументи для цього параметра та його аргумент-опціону . Однак відповідна реалізація також повинна дозволяти програмам вказувати параметр та параметр-аргумент у тому ж рядку аргументу без втручання символів .

Іншими словами: у цьому випадку, оскільки -dпараметр-аргумент опції є обов'язковим , ви можете вибрати, чи слід вказати роздільник як :

  • (s) ВСІ: окремий аргумент
  • (d) АБО: як значення, безпосередньо прикріплене до-d .

Після того як ви вибрали (-ла) або (г), важливий наступний рядковий-обчислювальний аналіз оболонки - (b) -

  • З підходом (ими) всі наступні форми є РІВНІВНИМИ:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • З підходом (d) всі наступні форми є РІВНІВНИМИ:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Еквівалентність пояснюється обробкою рядково-буквальної обробки оболонки :

Усі рішення, наведені вище, призводять до того самого рядка (у кожній групі) до моменту cutїх бачення :

  • (s) : cutбачить -d, як власний аргумент, а потім окремий аргумент, який містить пробіл - без лапок чи \префіксів !.

  • (d) : cutбачить -d плюс пробіл - без лапок і \префіксів! - як частина того ж аргументу.

Причина форм у відповідних групах в кінцевому рахунку однакова, двояка, заснована на тому, як оболонка аналізує рядкові букви :

  • Оболонка дозволяє визначати буквальне як через механізм, який називається цитуванням , який може приймати кілька форм :
    • одноцитувані рядки: вміст всередині '...'сприймається буквально і утворює єдиний аргумент
    • подвійне цитування рядків: вміст всередині "..."також утворює єдиний аргумент, але підлягає інтерполяції (розширює змінні посилання, такі як $varпідстановки команд ( $(...)або `...`) або арифметичні розширення ( $(( ... ))).
    • \-цитування окремих персонажів : \попередній один символ спричиняє інтерпретацію цього символу як буквальний.
  • Цитування доповнюється видаленням цитатою , а це значить , що після того , як оболонка розбирається в командному рядку, він видаляє ті лапки з аргументів (огороджувальних '...'або "..."або \примірників) - таким чином, команда викликається істота ніколи не бачить лапки .

36

Ви також можете сказати:

cut -d\  -f 2

Зауважте, що після нахилу нахилу є два пробіли.


30
Людина, яка знає, що "\" уникає наступного персонажа, дуже обережно відзначить, що прийшло далі. Використання "\" для втечі космічних символів - це дуже поширена ідіома.
Джонатан Хартлі

3
@ Джонатхан Хартлі, як правило, більшість кодів насправді не читаються :)
Luca Borrione

1
З точки зору linux / unix, це \ була моя перша спроба, і вона спрацювала. Я погоджуюсь, що це менш очевидно в порівнянні з ' ', але я впевнений, що багато хто радий читати це як заспокоєння поведінки. Для кращого розуміння дивіться коментар @ mklement0 нижче.
tresf

Поправка @JonathanHartley: " егоїстична людина, яка знає, що" \ "уникає наступного персонажа і передбачає, що всі інші також знають це". Для особистих проектів це не стосується, але в командній ситуації це припущення є дуже небезпечним (і, можливо, затратним).
Едуард Нікодей

1
@EduardNicodei О, я згоден. Ми говорили про читачів кодексу ("хто помічає ...?"), А не авторів. Але також для деяких команд чудово припускати певний рівень володіння. Залежить від оточення.
Джонатан Хартлі

5

Я щойно виявив, що ви також можете використовувати "-d ":

cut "-d "

Тест

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am

1
Справді - або '-d '.
mklement0

3
Зверніть увагу , що з cut«s перспектива всіх наступними однакова: "-d ", '-d ', -d" ", -d' ', і -d\<space>: всі форми безпосередньо додайте аргумент опції (пропуск) до опції ( -d) і результату в тій же самій рядку на той час cutїх бачать: один Аргумент, що містить d з пробілом, після того, як оболонка виконала вилучення цитати
mklement0

1
@ Відповідь mklement0 повинен бути відповідь. Це найповніше на цій сторінці (навіть якщо це коментар).
tresf

@QZSupport: Я ціную настрої та заохочення - це надихнуло мене на публікацію власної відповіді з додатковою довідковою інформацією.
mklement0

1
Lol захоплююче відкриття!
Гаррі

4

Ви не можете зробити це легко з вирізанням, якщо в даних є, наприклад, кілька пробілів. Я вважаю корисним нормалізувати введення для легшої обробки. Один фокус - використовувати sed для нормалізації, як показано нижче.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar

3

scut , скорочувальна утиліта (розумніша, але повільніша, яку я зробила), яка може використовувати будь-який регекс perl як маркер зламу. Розбиття на пробіли - це за замовчуванням, але ви також можете перерватися на мульти-чарові регулярні вирази, альтернативні регулярні вирази тощо.

scut -f='6 2 8 7' < input.file  > output.file

тож вищевказана команда би розбивала стовпці на пробілі та витягувала (на основі 0) cols 6 2 8 7 у цьому порядку.


0

У мене є відповідь (я визнаю дещо заплутану відповідь), яка включає sedрегулярні вирази та групи захоплення:

  • \S* - перше слово
  • \s* - роздільник
  • (\S*) - друге слово - захоплено
  • .* - решта лінії

Як sedвираз, групу захоплення потрібно уникнути, тобто \(і \).

У \1повертає копію захопленої групи, тобто друге слово.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Коли ви дивитесь на цю відповідь, її дещо заплутаність, і, можете подумати, навіщо турбуватися? Ну, я сподіваюся, що дехто може піти "Ага!" і буде використовувати цю схему для вирішення деяких складних проблем із вилученням тексту за допомогою одного sedвиразу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.