Bash 循环以按文件计算 php 个标签

Bash loop to count php tags by file

我想要一个 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

也可以转换成一行命令吗?

你写的是(或多或少)你想要的脚本。只需修复分配。将内容写入文件,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 作为开始标签。

任何时候你在 shell 中写一个循环只是为了操作文本,你的方法都是错误的。在这种情况下,您拥有的脚本和您选择的答案都将非常低效和脆弱,并且会产生奇怪的意外输出 and/or 语法错误,具体取决于您 运行 它们所在的目录的内容。

用于处理文本的 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 个进程,而不是 shell 脚本每个文件 4 个进程,因此效率会提高几个数量级,并且适用于任何文件名,包括那些包含白色的文件名space 甚至换行符。

请注意,就像您的 shell 循环的行为一样,上述内容实际上并没有检测到 bad.php 文件中的不匹配,因为缺少一个打开和 1 个缺少关闭。幸运的是,它也很容易增强,例如,告诉您 open/close 行不匹配的行号和内容,并在它们出现时报告它们:

$ 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 = [=13=]
}
/\?>/ {
    if (++end > beg) {
        print "Warning:", FILENAME, "missing open for the close at line", FNR, [=13=]
        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 作为上面的 var 名称而不是 open/close 因为 close() 是一个 awk 函数名称。