【问题标题】:How to pass a filename as a string to awk to parse for destination如何将文件名作为字符串传递给 awk 以解析目标
【发布时间】:2015-09-06 16:59:31
【问题描述】:

任务

我正在尝试将路径名/文件名传递给 awk,以利用其字段分隔符功能。我想解析路径名/文件名以查看它是否在系统的用户目录中。示例路径:

绝对路径:

/home/students/username               # VALID
/home/staff/username                  # VALID
/home/students/username/anythingElse  # VALID
/home/staff/username/anythingElse     # VALID
/home/notAccountStorage/anythingElse  # INVALID

相对路径(例如,pwd/current 为 /home/student/user/courseFiles):

../                                       # VALID /home/student/user
../otherDir                               # VALID /home/student/user/other
../.                                      # VALID /home/student/user
../..                                     # INVALID /home/student
../../otherDir                            # INVALID /home/student/otherDir

代码

我的想法是检查字符串是否以“/”开头,然后处理绝对路径,否则处理相对路径。

AWK 代码如下:

awk -F="/" '    BEGIN { directoryAccentCount=0                                                                  \
                        isValid=$FALSE;                                                                         \
                }                                                                                               \
                {                                                                                               \
                        # If the string starts with a "/", path is absolute                                     \
                        if ( $0 ~ /^\// ) {                                                                     \
                                # If either Student/Staff && Number of Fields must be great than 2              \
                                if ( ($2 == "student" || $2 == "staff") && NF > 2 ) isValid=$TRUE               \
                        } else {                                                                                \
                        # Path is relative                                                                      \
                                for (i = 1; i <= NF; i++) {                                                     \
                                        # Count how many directories the User wants to ASCEND towards ROOT      \
                                        if ( $i ~ /\.\./ ) { directoryAccentCount++ }                           \
                                        # If the difference between the Number of Fields and                    \
                                        # the Accent Count is greater than 2, isValid=$TRUE                     \
                                        difference=(NF - $directoryAccentCount)                                 \
                                        if ( $difference > 2 ) isValid=$TRUE                                    \
                        }                                                                                       \
                }                                                                                               \
                END { print $0 ":" $isValid }' << HERE $providedPath
HERE

错误

我尝试了上述代码的变体,但 awk 一直在尝试跟踪文件路径、打开文件并处理文件的文本。我想自己处理路径。

awk: fatal: 文件 `noCopyDir1' 是一个目录

【问题讨论】:

  • HERE $provicdedPath HERE 需要位于 3 个单独的行上。这应该可行,但不是传统的方法。 echo "$providedPATH" | awk -f .... 可能会更好。然后你可以exit 0 如果OK,exit 1(或其他)表示有问题。祝你好运。
  • 你把 awk 和 shell 搞混了。它们是具有自己的语法和用途的独立工具。尽快获取并阅读 Arnold Robbins 撰写的《Effective Awk Programming, 4th Edition》一书,直到您没有尝试使用 awk,因为您目前从根本上误解了它。
  • @Ed Morton - 我找到了使用 awk 的解决方案的答案,我在 shell 脚本中调用它。
  • 那么您找到了错误的“解决方案”,因为这不是 awk 最好解决的问题。 awk 是用于操作文本的工具。就这样。您可以修改 awk 来做其他事情,就像您可以修改 shell 来操作文本一样,但在这两种情况下,您都使用了错误的工具来完成这项工作。
  • @Ed Morton - 我愿意接受建设性的建议,为我想要完成的任务提供更好的工具。我在下面的回答可能会澄清我想要实现的目标。由于我的项目时间有限,阅读整本书并不是一个真正的选择。

标签: bash parsing awk ksh tcsh


【解决方案1】:

恕我直言,您的问题尚不清楚,但听起来您只是想检查文件中给出的路径是否存在。那将是:

while IFS= read -r path
do
    [[ -e "$path" ]] && echo "valid" || echo "invalid"
done < file

【讨论】:

  • 需要更严格的验证,但是是的,我确实在后面使用 awk 的几个逻辑步骤中使用了这个
  • 如果我有更多时间,我会重新编写问题,因为前两个答案发布的地方甚至不接近我正在寻找的解决方案。感谢观看
【解决方案2】:

您的解决方案太复杂了。您可以在 bash 中的一行内完成。可能有比我更短的解决方案:

[ -d "$(readlink -f $YOUR_PATH | awk -F/ '$2 == "home" && $3 != "" {print "/"$2"/"$3}')" ]

解释:

readlink -f $YOUR_PATH

这会将任何路径转换为绝对路径。

awk -F/ '$2 == "home" && $3 != "" {print "/"$2"/"$3}'

由于路径已经是绝对路径,所以我可以直接将前两个路径提取出来,但限制它在主文件夹下,它也在某个子文件夹下。

然后检查它是否是一个文件夹。

【讨论】:

    【解决方案3】:

    您可以尝试使用 而不是。它可以使用Cwd 和File::stat 模块轻松处理路径,例如:

    perl -mCwd=realpath -MFile::stat -E '
        $p = realpath($ARGV[0]); 
        say $p =~ m{\A/home/} && stat($p) ? q|VALID| : q|INVALID|' 
    '../../otherDir'
    

    它获取绝对路径,检查它是否是home 目录并且它存在。

    【讨论】:

      【解决方案4】:

      仅在相对路径的情况下确定目录上升/体面的简化逻辑。 awk 脚本利用逐个遍历字段的优势,在向根移动时返回负值,在远离根时返回正值。

       # Check that the distance from a User Directory
                      set movingDistance = `echo $argPath | awk -F'/' 'BEGIN{                                 \
                              distanceMoved=0                                                                 \
                      }                                                                                       \
                      {                                                                                       \
                              for ( i=1; i<NF; i++ ) {                                                        \
                                      if ( $i ~ /\.\./ ) {                                                    \
                                              distanceMoved--                                                 \
                                      } else {                                                                \
                                              distanceMoved++                                                 \
                                      }                                                                       \
                              }                                                                               \
                      }                                                                                       \
                      END {                                                                                   \
                              print distanceMoved                                                             \
                      }'`
      

      这是确定文件路径是在系统中的用户帐户之外还是保留在用户目录中的重要步骤,这就是我应用脚本的方式,但是,它可以在许多其他情况下使用。

      【讨论】:

      • 根本不清楚上面的目的是什么。如果您只想让 awk 计算输入流中有多少 /s 是 awk '{print gsub(/\//,"&amp;")}' 但为什么要测试 .. 以及您将如何处理 dir//dir2?它在使用distanceMoved 变量初始化和打印方面也存在根本缺陷。我们无法通过阅读不执行您想要执行的操作的脚本来判断您想要执行的操作 - 我强烈建议您发布一个新的、更清晰的问题。
      猜你喜欢
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      相关资源
      最近更新 更多