我有一个固定宽度的文件。它有两个日期字段,分别位于每行的位移日期 1 (1-8) 和日期 2 (11-18)。如果 date1 为空或空白,我想将 date1 替换为 date2。
输入:
a20201005xy20201209mnkm
b20201001dt20210526nhyg
c mn20210217bgyt
d yr20210314vfgy
期望输出:
a20201005xy20201209mnkm
b20201001dt20210526nhyg
c20210217mn20210217bgyt
d20210314yr20210314vfgy
法典:
#!/usr/bin
while read -r line; do
date1=`echo ${line:1:8}`
date2=`echo ${line:11:8}`
echo $date1 $date2
if [[ ${date1} == " " ]]
then
sed -i 's/${date1}/${date2}/g' $line
fi
done < replace
感谢您的帮助!
赛勒斯对awk
有一个很好的答案。如果你不能使用FIELDWIDTHS=
,你可以对substr()
和sub()
做同样的事情,这将适用于所有awk
。您只需使用substr()
来检查以字符 2 开头的 8 个字符子字符串中的所有字符是否都是空格 ([[:blank:]]
) 字符。如果是,您只需将它们替换为从字符 12 开始的 8 个字符的子字符串,例如
awk '{
if (substr($1,2,8) ~ /^[[:blank:]]*$/) {
date = substr($0,12,8)
sub(/[ ]+/,date,$0)
}
}1' input.txt
(注:末尾的1
只是print
记录的简写)
如果你想缩短它一点,你可以简单地删除date
变量并用substr()
直接替换,例如sub(/[ ]+/,substr($0,12,8),$0)
,但这可能不太易读。
示例使用/输出
通过您在input.txt
中的输入,您将收到:
$ awk '{
> if (substr($1,2,8) ~ /^[[:blank:]]*$/) {
> date = substr($0,12,8)
> sub(/[ ]+/,date,$0)
> }
> }1' input.txt
a20201005xy20201209mnkm
b20201001dt20210526nhyg
c20210217mn20210217bgyt
d20210314yr20210314vfgy
仔细检查一下,让我知道这是否可行。
使用您显示的示例,请尝试以下操作。
awk '
match($0,/^[a-z][[:space:]]{8}/){
val=substr($0,RSTART,RLENGTH)
val2=substr($0,12,8)
sub(/[[:space:]]+$/,val2,val)
$0=val substr($0,RSTART+RLENGTH)
}
1
' Input_file
说明:为上述添加详细说明。
awk ' ##Starting awk program from here.
match($0,/^[a-z][[:space:]]{8}/){ ##using match function to match from starting with small letter followed by 8 spaces.
val=substr($0,RSTART,RLENGTH) ##Creating val which has matched sub string.
val2=substr($0,12,8) ##Creating val2 with sub string of 8 characters.
sub(/[[:space:]]+$/,val2,val) ##Substituting spaces in val with val2.
$0=val substr($0,RSTART+RLENGTH) ##Creating current line with value of val and sub string of matched string.
}
1 ##Printing current line.
' Input_file ##Mentioning Input_file name here.
如果perl
恰好是您的选择,请您尝试以下方法:
perl -pe '
$date1 = substr($_, 1, 8);
if ($date1 =~ /^s+$/) {
substr($_, 1, 8) = substr($_, 11, 8);
}
' file > newfile
-pe
选项通过放置即时代码来组成类似 awk 的单行代码 作为论据。- 变量
$_
是perl
的默认变量,它用作模式sed
的空间 . substr($_, 1, 8)
函数提取从偏移量开始的子字符串 1 和长度 8 的字符串$_
,用于保存当前行。- 正则表达式
/^s+$/
测试变量$date1
是否仅包含空格。 substr()
功能可以方便地用作lvalue
含义 它可以被分配。声明substr($_, 1, 8) = substr($_, 11, 8);
将右侧子字符串复制到左侧子字符串上。
如果你有更多的字段要替换,修改上面的代码会很容易 以满足您的要求。
如果您想使用"sed",请尝试以下操作:
$ sed 's/^(.) (..)(........)/1323/' input.txt
a20201005xy20201209mnkm
b20201001dt20210526nhyg
c20210217mn20210217bgyt
d20210314yr20210314vfgy
使用gnu-awk
您可以尝试以下单行:
awk 'length($1)<8 {$0 = gensub(/[[:blank:]]+/, substr($2, 3, 8), "1")} 1' file
a20201005xy20201209mnkm
b20201001dt20210526nhyg
c20210217mn20210217bgyt
d20210314yr20210314vfgy