很抱歉,问题很简单。我是一个shell脚本的初学者,我需要编写一个脚本,它将在mksh安装的机器上的文本文件上工作,但没有工作版本的sed或大多数gnu实用程序或兼容。
还没有安装dos2unix的版本。
该脚本接收一个dos格式的文件,但它包含的字符非常简单(只有字母和数字,每行长度低于20个字符,少于1000行),并且它读取文件字符通过角色将角色添加到"线"变量。当它到达回车符时,它会打印出该行。用法将是sh script.sh file.txt> newfile.txt。
脚本无法按预期工作,我不确定原因:
#!/bin/sh
riga="";
nomefile="$1";
while IFS='' read -r -n1 carattere;
do
if [[ $carattere != *$'\r'* ]]; then
riga="${riga}carattere";
elif [[ $carattere == *$'\r'* ]]; then
print "${riga%$}";
riga="";
fi
done < "$nomefile"
这是最初编写的脚本输出:
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
我在https://www.freebsd.org/cgi/man.cgi?query=ksh阅读了ksh的优秀手册页,并修改了脚本如下:
#!/bin/sh
#!i=0
#!
riga="";
nomefile="$1";
while IFS='' read -r -n1 carattere;
do
if [[ $carattere != *$'\r'* ]]; then
riga="${riga}$carattere";
elif [[ $carattere == *$'\r'* ]]; then
print "${riga%$}";
riga="";
fi
done < "$nomefile"
输出类似于我想要的,但在打印行之间插入空行:
ID
1
2
3
4
5
6
7
8
答案 0 :(得分:1)
好的,在更多地阅读了ksh手册页和一些测试后,我发现了什么不起作用。我的脚本的第一个版本没有正确地将我读到的字符附加到 riga 变量,因为我没有使用替换($)来附加 carattere 变量。
第二个版本按预期工作,但没有考虑到dos文件使用CRLF终止行的事实:我正在检查\ r \ n字符,这意味着\ n字符已添加到我的 riga 变量。我修改了第一个if条件来检查字符是否与\ n不同。
然后我的脚本中的另一个问题是,在我想要转换的文件结构中,有n行,最后一行没有终止。这意味着我的脚本不会写入 riga 变量中最后一行的字符,但它不会打印最后一行。我解决了在while循环后添加打印指令的问题,使用-n参数来避免在字符串后面打印换行符。
该脚本的最终版本是:
#!/bin/sh
#!i=0
#!^M
riga="";
nomefile="$1";
while IFS='' read -r -n1 carattere;
do
if [[ $carattere != *$'\r'* ]] && [[ $carattere != *$'\n'* ]]; then
riga="${riga}$carattere";
elif [[ $carattere == *$'\r'* ]]; then
print "${riga%$}";
riga="";
fi
done < "$nomefile"
print -n "${riga%$}";
感谢本杰明,他的评论让我朝着正确的方向解决我的问题。