bash字符串以空格和额外的定界符进行数组 [英] bash string to array with spaces and extra delimiters

查看:117
本文介绍了bash字符串以空格和额外的定界符进行数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以竖线("|")作为分隔符并包含空格的字符串创建数组.我已经逛了一会儿了,感谢如何在Bash中的定界符上拆分字符串?将字符串拆分为数组 a>还有更多.我已经接近了,但是还不能正常工作.两个主要问题是字符串中有空格,开始和结束定界符,并且某些字段为空白.另外,我不仅要回显这些值,还需要将它们分配给变量. 这是源数据的格式:

I'm trying to create arrays from strings that have pipe ("|") as delimiters and include spaces. I've been looking around for a while and I've gotten close thanks to sources like How do I split a string on a delimiter in Bash?, Splitting string into array and a bunch more. I'm close but it's not quite working. The two main problems are that there are spaces in the strings, there are starting and ending delimiters, and some of the fields are blank. Also, instead of just echoing the values, I need to assign them to variables. Here's the format of the source data:

|username|full name|phone1|phone2|date added|servers|comments|

示例:

|jdoe | John Doe| 555-1212 | |1/1/11 |  workstation1, server1 | added by me |

这就是我需要的:

Username: jdoe
Fullname: John Doe
Phone1: 555-1212
Phone2: 
Date_added: 1/1/11
Servers: workstation1, server1
Comments: guest account

我使用sed去除第一个和最后一个定界符以及每个定界符前后的空格,现在输入为:

I use sed to strip out the first and last delimiter and spaces before and after each delimiter, input is now:

jdoe|John Doe|555-1212||1/1/11|workstation1, server1|added by me

这是我尝试过的事情:

oIFS="$IFS"; IFS='|'
for line in `cat $userList`; do
  arr=("$line")
  echo "Username: ${arr[0]}"  #not assigning a variable, just testing the output
  echo "Full Name: ${arr[1]}"
  echo "Phone 1: ${arr[2]}"
  echo "Phone 2: ${arr[3]}"
  # etc..
done
IFS="$oIFS"

输出:

Username: 
Full Name: 
Phone 1:
Phone 2:
Username: jdoe
Full Name: 
Phone 1:
Phone 2:
Username: John Doe
Full Name: 
Phone 1:
Phone 2:

我尝试过的另一件事:

for line in `cat $userList`; do
  arr=(${line//|/ })
  echo "Username: ${arr[0]}"
  echo "Full Name: ${arr[1]}"
  echo "Phone 1: ${arr[2]}"
  echo "Phone 2: ${arr[3]}"
  # etc
done

输出:

Username: jdoe
Full Name: John
Phone 1:
Phone 2:
Username: Doe
Full Name: 555-1212
Phone 1:
Phone 2:

有什么建议吗?谢谢!

推荐答案

您的第一次尝试非常接近.主要问题是这些:

Your first attempt is pretty close. The main problems are these:

  • for line in `cat $userList`$IFS而不是换行符分割文件.因此,应在循环前设置IFS=$'\n',并在循环内设置IFS='|'. (顺便说一句,值得注意的是for ... in `cat ...`方法会先读取整个文件然后将其拆分,因此,如果文件很大,这不是最佳方法.基于read的方法会更好在这种情况下.)
  • 通过将$line用双引号引起来,
  • arr=("$line")可以防止单词拆分,因此使$IFS不相关.应该只是arr=($line).
  • 由于$line具有引导管道,因此您需要先将其剥离(通过编写类似$line="${line#|}"的内容),否则需要将arr视为基于1的管道.数组(由于${arr[0]},第一个管道之前的部分将为空).
  • for line in `cat $userList` splits the file by $IFS, not by line-breaks. So you should set IFS=$'\n' before the loop, and IFS='|' inside the loop. (By the way, it's worth noting that the for ... in `cat ...` approach reads out the entire file and then splits it up, so this isn't the best approach if the file can be big. A read-based approach would be better in that case.)
  • arr=("$line"), by wrapping $line in double-quotes, prevents word-splitting, and therefore renders $IFS irrelevant. It should just be arr=($line).
  • Since $line has a leading pipe, you either need to strip it off before you get to arr=($line) (by writing something like $line="${line#|}"), or else you need to treat arr as a 1-based array (since ${arr[0]}, the part before the first pipe, will be empty).

将其放在一起,您将得到以下内容:

Putting it together, you get something like this:

oIFS="$IFS"
IFS=$'\n'
for line in `cat $userList`; do
  IFS='|'
  arr=($line)
  echo "Username: ${arr[1]}"  #not assigning a variable, just testing the output
  echo "Full Name: ${arr[2]}"
  echo "Phone 1: ${arr[3]}"
  echo "Phone 2: ${arr[4]}"
  # etc..
done
IFS="$oIFS"

(注意:我并不担心字段的前导空格和尾随空格,因为我可以分别执行该步骤"部分...还是我误会了这一点?您是否也需要该部分的帮助? ?)

(Note: I didn't worry about the fields' leading and trailing spaces, because of the "I can do that step separately" part . . . or did I misunderstand that? Do you need help with that part as well?)

这篇关于bash字符串以空格和额外的定界符进行数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆