управление полями, разделенными запятыми

В контексте задания «Изучение сценариев Linux/оболочки» я бы предложил что-то вроде этого:

mydir=$1

for f in "$mydir"/*
do
  printf "%s %d\n" "$f" $(find "$mydir" -name "$f" -print 2>/dev/null | wc -l)
done

Корректировки из вашего сценария:

  1. нет необходимости cd в каталог, чтобы ls его
  2. не нужно awk имя файла; вы могли бы просто ls это, но...
  3. запуск ls ... awk отдельно от find означает, что вы получили отдельный вывод
  4. нет необходимости специально печатать вывод find, если все, что вы делаете, это его подсчет
  5. нет необходимости сортировать вывод, если все, что вы делаете, это подсчет
  6. нет необходимости использовать uniq если вы пытаетесь перехватить все
  7. я взял на себя смелость удалить -типа f на тот случай, если ваше задание потребует, чтобы вы нашли каталоги одного и того же name
  8. добавлено -name "$f" чтобы найти соответствовали только файлам с совпадающими именами
  9. используйте printf для объединения имени файла и числа в та же строка вывода
  10. нет необходимости анализировать вывод ls, чтобы получить имя(я) файла(ов); это то, что for f в "$mydir"/* -- в частности, * -- делает; он расширяется, чтобы соответствовать именам файлов.

Я также процитировал все ваши варианты использования переменных на тот случай, если пользователь предоставит имя файла, такое как "этот файл".

Это не будет показывать скрытые файлы в выводе; вы можете добавить shopt -s dotglob, чтобы "$mydir"/* также расширялся для соответствия точечным файлам (скрытым файлам).

В качестве дополнительной оговорки: это приведет к неправильному подсчету имен файлов, содержащих символы новой строки, при условии, что пользователь передает имя файла, содержащее новую строку, для поиска.

0
15.06.2017, 17:37
3 ответа

Perl

perl -ne 'print if /^([^,]*,){2}\h*[^\h,]/' yourcsvfile

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

perl -F, -lane 'print if $F[2] =~ /\S/' yourcsvfile

Мы разбиваем строку на поля с разделителями-запятыми, хранящиеся в массиве @F, затем ищем 3-й $F[2]и смотрим, есть ли в нем хотя бы один неверный -whitespace \Sв нем.

Sed

sed -e '
   s/,/\n/2;s/,/\n/2
   /\n[[:space:]]*\n/d
   y/\n/,/
' yourfile.csv

Выделите третье поле символом новой строки. Затем, когда есть все пробелы или ничего между двумя маркерами => строка, которую нужно удалить. OTW, мы меняем маркеры, и sedпо умолчанию печатает пространство шаблонов.

0
28.01.2020, 02:16

Используя GNU awk:

$ awk -F' *, *' '$3' file
x, xx, xxx, xxxx, , , ,  

С помощью -F мы устанавливаем разделитель полей в регулярное выражение ␣*,␣* (пробел, звездочка, запятая, пробел, звездочка). Это выражение соответствует любой запятой, окруженной нулем или более пробелами.

Фактический скрипт awk — это всего лишь $3, что означает, что если третье поле не пусто, строка будет напечатана.

3
28.01.2020, 02:16

awkрешение:

awk -F, '$3!~/^[[:space:]]*$/' file

Выход:

x, xx, xxx, xxxx,,,,

  • -F,-разделитель полей

  • $3!~/^[[:space:]]*$/-учитываются только те строки, в которых не -пусто 3-е поле (не состоит из пробелов)

2
28.01.2020, 02:16

Теги

Похожие вопросы