`echo "${var}"` 输出前导空格

`echo "${var}"` 输出前导空格

有人可以帮助我吗?我正在尝试创建很多文件,但是当我尝试使用 echo 写入它时,它会添加一个空格和单引号,例如:

' (here is the space)  file.tmp' 

'  file1.tmp'

'  file3.tmp' 

代码是这样的。


cat limpio.tmp | while read line; do
  srcip=$(echo $line | awk -F"," '{print $1}')
  destip=$(echo $line | awk -F"," '{print $2}')
  port=$(echo $line | awk -F"," '{print $NF}')
  echo "${srcip}" >> "$destip.tmp"
done

当我尝试使用 cat 迭代并查看其内容时,问题就出现了,但由于空格而无法执行。

非常感谢

答案1

echo实用程序插入空格,但仅在输出参数时作为参数之间的分隔符:

$ echo 1    2 3       4 'A B     C'
1 2 3 4 A B     C

B和之间的空格C被保留,因为它们是 的同一参数的一部分echo

所以这不是echo那个插入空格,而是您的数据已经包含空格。

我假设您看到的单引号是ls系统输出的一部分(请参阅为什么“ls”突然用单引号将空格包裹起来?),或者可能是 shell 运行时的跟踪输出的一部分set -x(参见为什么 bash 在执行命令之前会在命令中未加引号的失败路径名扩展中添加单引号?)。也就是说,它实际上并不是文件名的一部分,而只是某些工具呈现名称的方式。

例如,假设您的输入类似于

174.18.418.83, 10.404.401.94, 53144
174.18.418.83, 10.404.401.94, 53144
174.18.418.83, 10.404.401.94, 53144

您会注意到逗号分隔符后面有空格。如果您使用逗号作为分隔符从上述文件中读取第二个字段,则您将保留字段开头的空格,如果您使用该数据作为文件名,则文件名将以空格开头。

(细心的读者会注意到问题中的代码使用了line不带引号的变量,这意味着 shell 会在空格上分割变量的值并echo以单独的参数呈现,例如174.18.418.83,10.404.401.94,53144。所以是真的从某种意义上说,它echo插入了需要删除的空格,但如果数据中没有空格/制表符,则不会这样做。也可以看看什么时候需要双引号?

解决方案是使用逗号和任何后续空白字符作为分隔符awk

awk -F ',[[:blank:]]*' '{ print $2 }'

该表达式,[[:blank:]]*匹配逗号后跟任意数量的空白字符。 “空白”字符是空格或制表符。, *如果您知道有文字空格,则可以将其更改为(“逗号,空格,星号”)。

现在避免打电话awk 输入文件中每一行的时间。

print中的语句可以awk以与在 shell 中重定向输出几乎相同的方式“重定向”,使用>后跟文件名。

您似乎想要使用的文件名是第二个字段中的任何内容,并.tmp附加。

这意味着您可以使用以下单个命令替换问题中的整个循环awk

awk -F ',[[:blank:]]*' '{ print $1 > ($2 ".tmp") }' limpio.tmp

该表达式的计算结果为添加到第二个字段中的内容所产生的($2 ".tmp")字符串。.tmp

使用>withprint意味着输出文件将在第一个文件上创建或截断(清空),print并且只有print在相同名称的后面才会追加新行。如果您要使用>>代替>,第一个print将追加到文件而不是截断文件。

这里没有内置的健全性检查,因此上面的内容可能会破坏系统上您有写访问权限的任何位置的重要文件,具体取决于输入的第二列中的内容。

如果您使用 GNU awk,那么这就是您需要做的。但是,如果您使用其他文件awk并且需要写入大量文件,则可能需要close()在处理文件时手动调用这些文件,否则可能会用完可用的文件描述符。

awk -F ',[[:blank:]]*' '{ fn = $2 ".tmp"; print $1 >>fn; close(fn) }' limpio.tmp

在这里,我将输出文件名保存在变量fn.然后,我将输出附加到该文件,然后关闭该文件。这确保了我不会耗尽可用的文件描述符,但如果我需要再次运行该命令,它也要求我始终使用>>print手动清理(删除)输出文件awk

GNUawk跟踪已打开的文件描述符数量,并在需要时开始关闭它们(如果稍后需要将更多数据写入文件,则重新打开文件以进行追加)。

也可以看看:

答案2

这是您最初发布的代码:

cat limpio.tmp | while read line; do
  srcip=$(echo $line | awk -F"," '{print $1}')
  destip=$(echo $line | awk -F"," '{print $2}')
  port=$(echo $line | awk -F"," '{print $NF}')
  echo "${srcip}" >> "$destip.tmp"
done

这是不必要的复杂。看到您正在读取逗号分隔的字段,您可以将它们直接读入变量:

while IFS=$' \t\n,' read -r srcip destip port junk ;do
  echo "$srcip" >> "${destip}.tmp"
done <limpio.tmp

答案3

最简单的修复可能是删除 中的双引号echo "${srcip}"

看看你自己:

var=' spacy '
echo X$(echo "$var")X
echo X$(echo $var)X

相关内容