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.