Я хотел бы иметь сценарий 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
Также это может быть преобразовано в однострочную команду?
Каждый раз, когда вы пишете цикл в оболочке, просто чтобы манипулировать текстом, у вас неправильный подход В этом случае ваш сценарий и выбранный вами ответ будут чрезвычайно неэффективными и хрупкими и будут вызывать странные неожиданные выходные данные и / или синтаксические ошибки в зависимости от содержимого каталога, в котором вы их запускаете.
Инструментом 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.
То, что вы написали, — это (более или менее) сценарий, который вы хотите. Просто исправьте задания. Запишите содержимое в файл, 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
в качестве вводного тега.