Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
借助bash代码逐行提取数据_Bash_Loops - Fatal编程技术网

借助bash代码逐行提取数据

借助bash代码逐行提取数据,bash,loops,Bash,Loops,我一直在努力编写一个新的bash脚本 我有一个包含以下内容的文本文件: /home/user1/public_html/pathtofile1 /home/user2/public_html/pathtofile2 /home/user3/public_html/packtofile3 我需要代码逐行读取文本文件,提取用户名以便挂起它,并将完整路径(/home/user1/public\u html/pathtofile1)作为挂起的原因 我需要它自动执行的操作示例: /scripts/sus

我一直在努力编写一个新的bash脚本

我有一个包含以下内容的文本文件:

/home/user1/public_html/pathtofile1
/home/user2/public_html/pathtofile2
/home/user3/public_html/packtofile3
我需要代码逐行读取文本文件,提取用户名以便挂起它,并将完整路径(/home/user1/public\u html/pathtofile1)作为挂起的原因

我需要它自动执行的操作示例:

/scripts/suspendacct user1 '/home/user1/public_html/pathtofile1' 1
/scripts/suspendacct user2 '/home/user1/public_html/pathtofile2' 1
/scripts/suspendacct user3 '/home/user1/public_html/pathtofile3' 1
我试过“for-loop”和“while-read-line”,但我没有运气

它还需要排除重复的用户名


如有任何意见,将不胜感激。提前感谢。

您可以在bash中循环时使用此

# already processed users
declare -A seen

while read -r line; do
   IFS=/ read -ra arr <<< "$line"
   u="${arr[2]}"
   [[ ! "${seen[$u]}" ]] && seen["$u"]=1 && /scripts/suspendacct "${arr[2]}" "$line"
done < file
#已处理用户
声明-已见
而read-r行;做

如果/read-raarr您的while循环方法很好,那么您可能只是在解析
行时遇到了问题。您可以使用参数扩展/子字符串提取子字符串替换来解析行中所需的信息。下面是参数扩展/子字符串提取的示例:

#!/bin/bash

while read -r line; do
    usr="${line#/*/}"
    usr="${usr%%/*}"
    # /scripts/suspendacct $usr "'$line'"                   # uncomment for use
    printf "/scripts/suspendacct %s '%s'\n" $usr "$line"    # delete for use
done

exit 0
临时输出

$ bash suspendusr.sh <dat/usrpathtofile.txt
/scripts/suspendacct user1 '/home/user1/public_html/pathtofile1'
/scripts/suspendacct user2 '/home/user2/public_html/pathtofile2'
/scripts/suspendacct user3 '/home/user3/public_html/packtofile3'

对每个用户使用单独的检查可能比将名称用作正则表达式要好。这将阻止任何较少包含的匹配。(例如,
user11
user111

尝试以下命令,该命令使用单一管道,并且避免在shell中循环:

sort -t/ -k3,3 -u file | 
  awk -F/ '{ print $3 "\t" $0 }' | 
    xargs -n 2 -J {} echo /scripts/suspendacct {} 1
删除上面的
echo
以实际运行
suspendacct

  • sort-t/-k3,3-u file
    根据分隔符
    //code>(
    -t/
    )按用户名(第三个字段(
    -k3,3
    )对输入文件进行排序,并消除重复用户名(
    -u
  • awk-F/'{print$3”\t“$0}'
    在每个输入行前面加上用户名:
    • $3
      是第三个字段,基于分隔符
      /
      -F/
    • $0
      是整个输入行
  • xargs-n2-J{}/scripts/suspendacct{}1
    为输入中的每对(
    -n2
    )空格分隔标记调用
    /scripts/suspendacct
    ,即为每对用户名路径对调用。
    • 注意,假设用户名和路径都没有嵌入空格(用户名的安全假设)——如果有,也可以解决;为了简洁起见,这里不讨论这个问题
    • -J{}
      只是为参数的位置定义占位符
      {}

展示您的尝试。
while
版本应该有效,是正确的方法。有关讨论和示例,请参阅。虽然输入错误很小,但第一个代码块中的
/home/user3/public\u html/packtofile3
应该是
/home/user3/public\u html/pathtofile3
?以下是我使用的while版本的示例。请注意,这是第一次在我的脚本中使用while read while read input do awk-F'/'{print$3}'| sort-u done<$textfile这给了我用户名的输出。当你说
'/home/user1/public_html/pathtofile1'
时,这里的许多答案都解释为你需要文字引号,所以,如果您是在命令行上编写的,那么他们提供给您的内容将相当于
“'/home/user1/public_html/pathtofile1'
。这是你真正想要的,还是你的意图被误解了?为了回答问题的人和未来读者的利益:如果答案解决了你的问题,请点击旁边的大复选标记接受它;如果您发现答案有帮助,请单击向上箭头图标进行向上投票(您可以同时进行这两项操作)。看见如果您的问题尚未完全回答,请提供反馈。谢谢,我将对此进行尝试并报告。这很好,但如果可能,我需要排除重复的用户名。嗯,请检查我的更新答案以了解唯一的处理。是的,谢谢,当它尝试挂起用户名时,它会显示无效用户。当我将/scripts/suspendacct“${arr[2]}'$line'”更改为echo“${arr[2]}'$line'”时,它以正确的格式输出。我在试着看看我能不能把它修好。谢谢大卫,你的方法是目前为止最好的。我忘了在我的原始帖子中提到我需要排除重复的用户名。好的,我将添加一个重复的检查。拆分
usr
是故意的吗?不管怎样,我都看不到用户提供的明确规范,但也许我只是缺少了它。当我学究的时候,
${uarray[@]}
应该是
“${uarray[@]}”
;否则,您可能会使用
${uarray[*]}
。您当然是正确的,但因为Linux系统的用户名不可能包含空格等。我没有引用,但我将修复:)
sort -t/ -k3,3 -u file | 
  awk -F/ '{ print $3 "\t" $0 }' | 
    xargs -n 2 -J {} echo /scripts/suspendacct {} 1