Цикл Bash для подсчета php-тегов по файлам

Я хотел бы иметь сценарий bash, который подсчитывает, сколько случаев найти потерянные теги. Я думаю, что это будет что-то вроде

Команда, которую я бы использовал для подсчета вхождений, это grep -o »

Может быть

for i in *.php; do
open = grep -o "<?php" $i | wc -l
close = grep -o "?>" $i | wc -l
echo $i open close
done

file1.php 5 5
file2.php 4 5

Также это может быть преобразовано в однострочную команду?

0

Решение

Каждый раз, когда вы пишете цикл в оболочке, просто чтобы манипулировать текстом, у вас неправильный подход В этом случае ваш сценарий и выбранный вами ответ будут чрезвычайно неэффективными и хрупкими и будут вызывать странные неожиданные выходные данные и / или синтаксические ошибки в зависимости от содержимого каталога, в котором вы их запускаете.

Инструментом UNIX для работы с текстом является awk — просто используйте его (в этом случае я использую GNU awk для ENDFILE):

$ cat good.php
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php echo '<p>Hello World</p>'; ?>
<?php echo '<p>Goodbye Cruel World</p>'; ?>
</body>
</html>

.

$ cat bad.php
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php echo '<p>Hello World</p>';
<?php echo '<p>Goodbye Cruel World</p>'; ?>
<?php echo '<p>Hello Again World</p>'; ?>
echo '<p>Goodbye Again Cruel World</p>'; ?>
</body>
</html>

.

awk '/<\?php/{++beg} /\?>/{++end} ENDFILE{print FILENAME, beg, end; beg=end=0}' *.php
bad.php 3 3
good.php 2 2

В приведенном выше примере используется всего 1 процесс для всех файлов вместо 4 на файл для сценария оболочки, поэтому он будет на несколько порядков эффективнее и будет работать для ЛЮБЫХ имен файлов, включая те, которые содержат пробелы или даже переводы строк.

Обратите внимание, что, подобно тому, как будет работать ваш цикл оболочки, вышеприведенное фактически не обнаруживает несоответствия в файле bad.php, так как отсутствует одно открытое и 1 отсутствует закрытое. К счастью, это также легко улучшить, скажем, сказать вам номера строк и их содержание, где строки открытия / закрытия не совпадают, и сообщить о них по мере их появления:

$ awk '
FNR==1 { beg=end=0 }
/<\?php/ {
if (beg++ > end) {
print "Warning:", FILENAME, "missing close for the open at line", begFnr, begRec
beg--
}
begFnr = FNR
begRec = $0
}
/\?>/ {
if (++end > beg) {
print "Warning:", FILENAME, "missing open for the close at line", FNR, $0
end--
}
}
ENDFILE {
if (beg > end) {
print "Warning:", FILENAME, "missing close for the open at line", begFnr, begRec
}
}
' *.php
Warning: bad.php missing close for the open at line 6  <?php echo '<p>Hello World</p>';
Warning: bad.php missing open for the close at line 9  echo '<p>Goodbye Again Cruel World</p>'; ?>

Кстати я использую beg/end как имена вар вместо выше open/close так как close() это имя функции awk.

1

Другие решения

То, что вы написали, — это (более или менее) сценарий, который вы хотите. Просто исправьте задания. Запишите содержимое в файл, chmod +x файл и вуаля.

#!/bin/bash
for i in *.php
do
open=$(grep -o "<?php" $i | wc -l)
close=$(grep -o "?>" $i | wc -l)
echo $i open close
done

Обязательно используйте <?php в качестве вводного тега.

1

По вопросам рекламы [email protected]