unix - кількість стовпців у файлі


79

Дано файл із такими даними (тобто файл stores.dat)

sid|storeNo|latitude|longitude
2|1|-28.03720000|153.42921670
9|2|-33.85090000|151.03274200

Якою буде команда для виведення кількості імен стовпців?

тобто у наведеному вище прикладі це буде 4. (кількість символів контуру + 1 у першому рядку)

Я думав приблизно так:

awk '{ FS = "|" } ; { print NF}' stores.dat

але він повертає всі рядки замість лише першого, а для першого - 1 замість 4

Відповіді:


120
awk -F'|' '{print NF; exit}' stores.dat 

Просто киньте відразу після першого рядка.


4
абоawk -F'|' 'NR==1{print NF}' stores.dat
— jaypal singh

11
@JaypalSingh: це прочитає весь файл - не потрібно цього, краще зупинитись раніше.
— Mat

Здається, вони обидва повертають однаковий правильний вивід, чи є якісь переваги в продуктивності 1 над іншими (або якісь інші переваги)?
— toop

2
@toop: так, див. мій попередній коментар. Моя версія читатиме лише один блок із файлу, а Jaypal - весь файл.
— Мат

1
@Mat Ви на місці! @loop Mat абсолютно правильний. exitце правильний спосіб зробити це. Не потрібно читати весь файл, якщо ви хочете знати лише кількість стовпців. +1 :)
— jaypal singh

37

Це обхідне рішення (для мене: я не часто використовую awk):

Відображає перший рядок файлу, що містить дані, замінює всі труби на нові рядки, а потім підраховує рядки:

$ head -1 stores.dat | tr '|' '\n' | wc -l

9
Для файлів зі стовпцями maaany (думаю, дані SNP) це шлях. Рішення Mat повернуло "awk: перевищено обмеження програми: максимальна кількість полів = 32767."
— The Unfun Cat

11

Якщо ви не використовуєте пробіли там, ви зможете використовувати | wc -wз першого рядка.

wc- це "Підрахунок слів", який просто підраховує слова у вхідному файлі. Якщо ви надішлете лише один рядок, він покаже вам кількість стовпців.


Я спробував: head -1 stores.dat | wc -w Але це не повертає того, що я шукаю
— занадто

Це тому, що ви не замінюєте |пробіл - wcбуде рахувати слова, які мають бути розділені пробілом. Використанняhead -1 stores.dat | tr '|' ' ' | wc -w
— Том ван дер Вердт

2
Будь ласка, додайте свій коментар до відповіді для повноти.
— Xofo


2

Рішення Perl, подібне до рішення Mat's awk:

perl -F'\|' -lane 'print $#F+1; exit' stores.dat

Я перевірив це на файлі зі 1000000 стовпцями.


Якщо роздільник поля - пробіл (один або кілька пробілів або табуляцій) замість конвеєра:

perl -lane 'print $#F+1; exit' stores.dat

1

Якщо у вас встановлений python, ви можете спробувати:

python -c 'import sys;f=open(sys.argv[1]);print len(f.readline().split("|"))' \
    stores.dat

у цьому конкретному випадку він коротший для читання зі стандартного вводуcat x.txt | python -c "print raw_input().count('|') + 1"
— Lie Ryan

коротше так, але не швидше, якщо багато довгих файлів! Я припустив, що він хоче швидшого рішення на очах чистих (мається на увазі великих) файлів даних.
— Дон Питання

1

Зазвичай це те, що я використовую для підрахунку кількості полів:

head -n 1 file.name | awk -F'|' '{print NF; exit}'

1

виділіть будь-який рядок у файлі (у прикладі нижче, це 2-й рядок) і підрахуйте кількість стовпців, де роздільником є ​​пробіл:

sed -n 2p text_file.dat | tr ' ' '\n' | wc -l

0

На основі відповіді Кет Керр. Ця команда працює на solaris

awk '{print NF; exit}' stores.dat

І тоді ви знаходитесь на прийнятій відповіді мінус правильний роздільник поля. Це поверне "1" для прикладу вводу.
— Бенджамін В.

По суті, це те саме, що прийнята відповідь без роздільника поля, як Бежамін каже, що повертає 1, але повинна працювати для файлів з обмеженим простором.
— discipulus


0

Належне чисте шлях

Під bash ви можете просто:

IFS=\| read -ra headline <stores.dat
echo ${#headline[@]}
4

Набагато швидше, як без вилок , і багаторазового використання, оскільки $headlineутримують повну лінію голови. Ви можете, для зразка:

printf " - %s\n" "${headline[@]}"
 - sid
 - storeNo
 - latitude
 - longitude

Nota Цей синтаксис буде правильно керувати пробілами та іншими символами в іменах стовпців.

Альтернатива: сильна двійкова перевірка максимальних стовпців у кожному рядку

Що робити, якщо якийсь рядок містить кілька зайвих стовпців?

Ця команда буде шукати більший рядок, рахуючи роздільники :

tr -dc $'\n|' <stores.dat |wc -L
3

Є максимум 3 роздільники, потім 4 поля.

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