3

Я новичок в этом ... Мне нужен скрипт, который получает каталог в качестве параметра и печатает имена файлов, которые имеют от 15 до 50 строк, но я не знаю, как использовать вывод wc в if -sentence:

#!/bin/bash
for f in `ls`; do
  echo "File -> $f"
  cat $f | wc -l
done

Как получить параметр? И как мне назначить вывод wc переменной?

3 ответа3

7

Параметры могут быть получены как $1 , $2 и т.д., Или $* для всех из них.

Существует также массив $@ , который обычно используется как "$@" в качестве лучшей версии $* . Другое возможное использование - ${@:3} что означает «все аргументы, начинающиеся с 3-го».

Чтобы получить вывод команды, используйте $( ... ) или ее более старую форму ` ... ` . Обычно рекомендуется всегда использовать $() поскольку он может быть вложенным, например, blah=$(cat /blah/$(blah)/blah) .

#!/usr/bin/env bash

for dir in "$@"; do
    for file in "$dir"/*; do
        lines=$(wc -l < "$file")
        if (( lines >= 15 && lines <= 50 )); then
            echo "File -> $file ($lines lines)"
        fi
        # another possible syntax:
        # if [ "$lines" -ge 15 ] && [ "$lines" -le 50 ]
        # or:
        # if [[ "$lines" -ge 15 && "$lines" -le 50 ]]
    done
done

Полезные ресурсы:

3

Вот еще один способ сделать это с помощью awk:

#!/usr/bin/env bash
for dir in "$@"; do
  for file in "$dir"/*; do 
    awk 'END{if(NR>=15 && NR<=50){print FILENAME}}' "$file"; 
  done
done

ОБЪЯСНЕНИЕ: awk (и его многочисленные варианты, такие как gawk mawk т.д.) Читают файл построчно. Переменная NR является текущим номером строки. Блок END{} будет выполнен, когда будет достигнута последняя строка входного файла, и в этот момент NR будет числом lnes в файле. Наконец, FILENAME - это имя файла, который обрабатывается в данный момент. Таким образом, скрипт печатает имя файла, если количество увиденных строк составляет от 15 до 50.

Точно так же вы можете сделать это с Perl:

#!/usr/bin/env bash
for dir in "$@"; do
  for file in "$dir"/*; do 
      perl -ne 'END{if($. >=15 && $. <=50){print "$ARGV\n"}}' "$file"
  done
done

ОБЪЯСНЕНИЕ: perl -ne также будет читать файл построчно. В Perl номер текущей строки хранится в $. и блок END работает так же, как в awk . $ARGV - это аргумент, передаваемый в командной строке, имя файла, которое будет напечатано, только если оно содержит правильное количество строк.

Ваш лучший выбор, вероятно, будет bash и wc ответом @grawity, но реализация wc не повлияет на них и должна хорошо работать на любом * nix.

2

Создайте несколько файлов:

$ for i in `seq -w 1 60`; do seq -w 1 $i > $i.lines; done

Печатайте только те, которые соответствуют критериям:

$ wc -l * | awk '$1 >= 15 && $1 <= 50 { print $2 }' | column
15.lines        23.lines        31.lines        39.lines        47.lines
16.lines        24.lines        32.lines        40.lines        48.lines
17.lines        25.lines        33.lines        41.lines        49.lines
18.lines        26.lines        34.lines        42.lines        50.lines
19.lines        27.lines        35.lines        43.lines
20.lines        28.lines        36.lines        44.lines
21.lines        29.lines        37.lines        45.lines
22.lines        30.lines        38.lines        46.lines

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .