我需要将test.txt文件转换为带列文件。
如果每个关键字后的行数相同但在此示例中不同,我知道如何用awk进行转换。
awk 'NR % 5 {printf "%s ", $0; next}1' test.txt
如果行数相同,则为代码,但此行不适用于此输入文件。
要转换吗?请告知。
test.txt
"abc"
4
21
22
25
"standard"
1
"test"
4
5
10
11
12
预期输出:
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
答案 0 :(得分:2)
$ awk '{printf "%s%s", (/^"/ ? ors : OFS), $0; ors=ORS} END{print ""}' file
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
答案 1 :(得分:0)
有点魔术,但在这种情况下有效:
sed -z 's/\n"/\n\x01"/g' |
tr '\n' ' ' |
tr $'\x01' '\n'
" ... "
之间的字符串。所以:sed
,在文件中的所有位置,在换行符和"
之间放置了一个除法符(我选择了十六进制的0x01)。请注意,-z
是gnu扩展名。0x01
个字节替换为换行符。此方法有点棘手,但是很简单,并且在标头在行首以某些字符开头的情况下可以使用。
可通过tutorialspoint获得实时版本。
例如,使用sed
而不使用gnu扩展名即可获得
sed '2,$s/^"/\x01"/'
即。如果行以"
开头则大于第二行,然后在行的开头添加0x01
字节。
答案 2 :(得分:0)
POSIX awk:
checked
或使用$ awk '/^"/{if (s) print s; s=$0; next} {s=s OFS $0} END{print s}' file
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
:
perl
如果您的字段中没有空格,则可以使用简单的$ perl -0777 -lnE 'for (/^"[^"]+"\R(?:[\s\S]+?)(?=^"|\z)/mg) {tr /\n/ /; say} ' file
和tr
管道:
sed
或GNU sed:
$ cat file | tr '\n' ' ' | sed -E 's/ ("[^"]*")/\
\1/g'
答案 3 :(得分:0)
使用GNU awk
$ awk -v RS='\n"' '{$1=$1; printf "%s", rt $0; rt=RT}' file
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
答案 4 :(得分:0)
尽管建议使用getDollarValue
或awk
解决方案,但由于该问题也被标记为sed
,因此您可以通过简单的读取循环和标志变量来控制所有操作第一次迭代的换行输出。本质上,您正在读取每一行,并使用字符串索引 parameterexpandment 来测试第一个字符是否为非数字,并且在第一个迭代中仅输出字符串,对于所有其他迭代,则输出以bash
开头的字符串。如果该行以数字开头,则只需在其前面输出一个空格即可。
例如:
'\n'
使用/输出示例
#!/bin/bash
declare -i n=0 ## simple flag to omit '\n' on first string output
while read -r line; do ## read each line
[[ ${line:0:1} =~ [^0-9] ]] && { ## begins with non-digit
## 1st iteration, just output $line, rest output '\n$line'
((n == 0)) && printf "%s" "$line" || printf "\n%s" "$line"
} || printf " %s" "$line" ## begins with digit - output " $line"
n=1 ## set flag
done < "$1"
echo "" ## tidy up with newline
虽然$ bash fmtlines test.txt
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
和awk
通常会更快(作为一般规则),但这里只不过是sed
循环和一些条件和参数扩展而已,它是本机bash解决方案比较起来还不错。
仔细研究一下,如果您有任何疑问,请告诉我。