Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.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_Shell_Sh - Fatal编程技术网

Bash 如果用制表符隔开,则无法识别单词

Bash 如果用制表符隔开,则无法识别单词,bash,shell,sh,Bash,Shell,Sh,我有一个问题,就是如果文本文件中的单词是用制表符而不是空格隔开的,程序就无法读取每个单词 例如,下面是一个文件 part_Q.txt: NWLR35MQ 649 HCDA93OW 526 abc 1 def 2 ghi 3 NWLR35MQ 649 HCDA93OW 526 def 2 ghi 3 NWLR35MQ 649 HCDA93OW 526 abc 1 def 2 ghi 3 #!/bin/sh tempCtr=0 realCtr=0 copyCtr=

我有一个问题,就是如果文本文件中的单词是用制表符而不是空格隔开的,程序就无法读取每个单词

例如,下面是一个文件

part_Q.txt:

NWLR35MQ        649
HCDA93OW        526
abc 1
def 2
ghi 3
NWLR35MQ
649
HCDA93OW
526
def
2
ghi
3
NWLR35MQ
649
HCDA93OW
526
abc
1
def
2
ghi
3
#!/bin/sh

tempCtr=0
realCtr=0
copyCtr=0
while IFS= read -r line || [[ -n $line ]]; do
   IFS=' '
   tempCtr=0
   for word in $line; do
    temp[$tempCtr]="$word"
    let "tempCtr++"
   done 
   # if there are exactly 2 fields in each line, store ID and quantity
   if [ $tempCtr -eq 2 ]
   then
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    let "copyCtr++"
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    copyCtr=0
   fi
done < part_Q.txt

for value in "${part_Q[@]}"; do
    echo $value
done
  • 请注意,在“abc”和“1”之间有一个选项卡,而不是空格
  • 还要注意,“NWLR35MQ”和“649”之间没有制表符,但都是空格。第二行也一样
输出:

NWLR35MQ        649
HCDA93OW        526
abc 1
def 2
ghi 3
NWLR35MQ
649
HCDA93OW
526
def
2
ghi
3
NWLR35MQ
649
HCDA93OW
526
abc
1
def
2
ghi
3
#!/bin/sh

tempCtr=0
realCtr=0
copyCtr=0
while IFS= read -r line || [[ -n $line ]]; do
   IFS=' '
   tempCtr=0
   for word in $line; do
    temp[$tempCtr]="$word"
    let "tempCtr++"
   done 
   # if there are exactly 2 fields in each line, store ID and quantity
   if [ $tempCtr -eq 2 ]
   then
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    let "copyCtr++"
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    copyCtr=0
   fi
done < part_Q.txt

for value in "${part_Q[@]}"; do
    echo $value
done
但是,如果我在文件中用空格替换“abc”和“1”之间的制表符,那么它将正确输出,如下所示

预期输出:

NWLR35MQ        649
HCDA93OW        526
abc 1
def 2
ghi 3
NWLR35MQ
649
HCDA93OW
526
def
2
ghi
3
NWLR35MQ
649
HCDA93OW
526
abc
1
def
2
ghi
3
#!/bin/sh

tempCtr=0
realCtr=0
copyCtr=0
while IFS= read -r line || [[ -n $line ]]; do
   IFS=' '
   tempCtr=0
   for word in $line; do
    temp[$tempCtr]="$word"
    let "tempCtr++"
   done 
   # if there are exactly 2 fields in each line, store ID and quantity
   if [ $tempCtr -eq 2 ]
   then
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    let "copyCtr++"
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    copyCtr=0
   fi
done < part_Q.txt

for value in "${part_Q[@]}"; do
    echo $value
done
它正确显示文件中的所有单词。如何显示所有单词,而不考虑制表符或空格?它应该显示两种情况下的所有单词。似乎该程序将tab视为一个字符

下面是源代码:

NWLR35MQ        649
HCDA93OW        526
abc 1
def 2
ghi 3
NWLR35MQ
649
HCDA93OW
526
def
2
ghi
3
NWLR35MQ
649
HCDA93OW
526
abc
1
def
2
ghi
3
#!/bin/sh

tempCtr=0
realCtr=0
copyCtr=0
while IFS= read -r line || [[ -n $line ]]; do
   IFS=' '
   tempCtr=0
   for word in $line; do
    temp[$tempCtr]="$word"
    let "tempCtr++"
   done 
   # if there are exactly 2 fields in each line, store ID and quantity
   if [ $tempCtr -eq 2 ]
   then
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    let "copyCtr++"
    part_Q[$realCtr]=${temp[$copyCtr]}
    let "realCtr++"
    copyCtr=0
   fi
done < part_Q.txt

for value in "${part_Q[@]}"; do
    echo $value
done
#/垃圾箱/垃圾箱
tempCtr=0
realCtr=0
copyCtr=0
而IFS=read-r行| |[[-n$line]];做
如果=“”
tempCtr=0
对于$line中的单词;做
临时[$tempCtr]=“$word”
让“tempCtr++”
完成
#如果每行正好有2个字段,则存储ID和数量
如果[$tempCtr-等式2]
然后
部分Q[$realCtr]=${temp[$copyCtr]}
让“realCtr++”
让“copyCtr++”
部分Q[$realCtr]=${temp[$copyCtr]}
让“realCtr++”
copyCtr=0
fi
完成
您可以通过一行代码来解决这个问题(如示例中所示)

cat part_Q.txt | tr $'\t' $'\n' | tr -s ' ' $'\n'
哪个

  • 首先
    tr
    将选项卡转换为新行,然后
  • tr
    也解析空间(
    -s
注意:对于
tr
,在bash中的
\t
ab和
\n
ewline字符之前需要
$


既然已经提到了这一点,
awk
也有帮助:

awk 'NF==2{print $1"\n"$2}' part_Q.txt

其中,
NF==2
甚至只考虑使用带有2个“单词”的行。

您想做什么?如果输出是您唯一的目标,那么这可以很容易地实现:

$ cat <<EOF | sed -E 's/[[:blank:]]+/\n/'
NWLR35MQ        649
HCDA93OW        526
abc 1
def 2
ghi 3
EOF

NWLR35MQ
649
HCDA93OW
526
abc
1
def
2
ghi
3

$catAwk比循环快,但以下是如何通过循环实现这一点:

realCtr=0
while read -r x1 x2 x3; do
   if [ -n "${x2}" ] && [ -z "${x3}" ]; then
      echo 2=$x2
    part_Q[realCtr]="${x1}"
   (( realCtr++ ))
    part_Q[realCtr]="${x2}"
   (( realCtr++ ))
   fi
done  < part_Q.txt

echo "Array (2 items each line):"
echo "${part_Q[@]}" | sed 's/[^ ]* [^ ]* /&\n/g'
realCtr=0
读取时-rx1x2x3;做
如果[-n“${x2}”]&&[-z“${x3}”];然后
回声2=$x2
第Q部分[realCtr]=“${x1}”
((realCtr++)
part_Q[realCtr]=“${x2}”
((realCtr++)
fi
完成
IFS='
更改为
IFS=$'\t'
解决了这个问题。

只是一个想法:您可以尝试预处理文件(或行)并用空格替换制表符。BTW <代码> AWK < /代码>绝对不会有这样的问题。请更改<代码> IFS= ''/c> > <代码> IFS= $'\/'代码>,但请考虑<代码> AWK < /代码>只删除<代码> IFS= 和<代码> IFS= ''/COD>代码>读取行
line将读取一行,无论是否存在空格<当您可以
awk'NF==2{print$1”\n“$2}”part_Q.txt
时,$line中的单词的code>默认情况下将拆分word.uooc。已调整,谢谢。通过从tr示例复制/粘贴使用管道您也不需要
cat
tr$'\t'$'\n“不必要地使用
IFS
。即使不设置它,它也可以工作。IFS的默认值足够了。