我收到了一个以管道分隔的文本文件,其中包含文件名和每个文件的一些索引信息。我的目标是使其成为制表符分隔文件。 但是,我想知道空条目的位置。这将完成,例如, lorem||dolor
变为lorem
'\t'
<empty>
'\t'
dolor
。
让我举几个例子来说明我得到的和所期望的:
多行示例:( N.B.每行的条目数相同。)
假设:
||dolor|sit
amet,||adipiscing|
sed|do|eiusmod|tempor
所需:
<empty> '\t' <empty> '\t' dolor '\t' sit '\n'
amet, '\t' <empty> '\t' adipiscing '\t' <empty> '\n'
sed '\t' do '\t' eiusmod '\t' tempor '\n'
开头和结尾的空条目。
假设:
|ut|labore||dolore||
所需:
<empty> '\t' ut '\t' labore '/t' <empty> '\t' dolore '\t' <empty> '\t' <empty>
(我不想要这些空格;我只是认为它会使所需的格式更容易阅读。)
问题来自连续的空条目。我给出的文件可以有1到36个连续的管道(0到37个连续的空条目。)
澄清
解决方案不一定是sed
,awk
,grep
,tr
等。这些只是我看过的解决方案。我也欢迎perl
或python
脚本(或任何其他我没有想过的想法)。
对于我在研究之前和研究期间所做的尝试,命令及其输出包含在图像 1 和文本文件 2 以免过度混乱这个问题。
我查找的内容的链接 - 使用sed
查找连续的管道(并替换任何此类管道系列):ref。 here;计算空字段的数量(可能需要知道需要多少<empty>
):ref。 here;最长的序列:ref here;
$ uname -a
CYGWIN_NT-10.0 A-1052207 2.5.2(0.297/5/3) 2016-06-23 14:29 x86_64 Cygwin
$ bash --version
GNU bash, version 4.3.42(4)-release (x86_64-unknown-cygwin) ...
$
我在Windows 10上运行此版本的Cygwin(因为这项工作需要它。)
我不清楚到底想要什么。
这是一个简短的例子,展示了我在开始和结束时对管道的要求:
(这是你会看到的,如果你输入第一行,点击输入,键入第二行,点击输入等,你需要键入它。它不能被复制/粘贴,因为{ {1}}仅在您在上一行按Enter后显示。)
>
$ cat > myfile.txt<<EOF
> ||foo|||bar||
> EOF
$ <**command-to-be-used**> myfile.txt | cat -A
<empty>^I<empty>^Ifoo^I<empty>^I<empty>^Ibar^I<empty>^I<empty>$
是我的^I
版本显示bash
的方式。根据我给出的一些示例文本给出的答案,我意识到在'\t'
之后我想要一个<empty>
(参见下面的命令)。请注意,收到的答案(感谢@Neil_McGuigan和@Ed_Morton)在labore
后提供'\t'
,而不是labore
。这是我的错,因为我在原始描述中不够清楚。道歉。
我能够通过对@ Neil_McGuigan的命令进行一些调整来实现我的目标。请注意,如果您要按照所示“逐行”键入,则需要在每行的末尾添加一个空格和<empty>
。
\
给出了结果:
$ echo "||lorem|ipsum||sit|amet,||||eiusmod|tempor|||labore|" |
awk '
{
$1=$1; n_empty=0;
for(i=1; i<=NF; i++)
{
if($i=="") {$i="<empty>"; n_empty++;}
};
print
}
END {print n_empty" entries are empty" | "cat 1>&2";}
' FS='|' OFS=$'\t'
| cat -A
再一次,对于那些不想滚动的人,这个输出如下:
<empty>^I<empty>^Ilorem^Iipsum^I<empty>^Isit^Iamet,^I<empty>^I<empty>^I<empty>^Ieiusmod^Itempor^I<empty>^I<empty>^Ilabore^I<empty>$
9 entries are empty
(请注意,写入<empty>^I<empty>^Ilorem^Iipsum^I<empty>^Isit^Iamet,^I<empty>^I<empty>^I<empty>^Ieiusmod^Itempor^I<empty>^I<empty>^Ilabore^I<empty>$
9 entries are empty
的空条目的数量不是必需的,但它很不错。)
很抱歉不清楚我想要什么。
感谢@Neil_McGuigan和@Ed_Morton,我能够得到我正在搜索的解决方案。我的最后命令如下:
stderr
万一你不想滚动,这里是相同的命令:
$ awk '{$1=$1; n_empty=0; for(i=1; i<=NF; i++) {if($i=="") {$i="<empty>"; n_empty++;}}; print;} END {print n_empty" entries are empty" | "cat 1>&2";}' FS='|' OFS=$'\t' file_pipe-delim.txt > file_tab-delim.txt
$
以下是制作,转换和保存文件的示例:
(这是你会看到的,如果你输入第一行,点击输入,键入第二行,点击输入等,你需要键入它。它不能被复制/粘贴,因为{ {1}}仅在您在上一行按Enter后显示。)
$ awk '{$1=$1; for(i=1; i<NF; i++){ if($(i)=="")$(i)="<empty>" }; print}'
FS='|' OFS=$'\t' file_pipe-delim.txt | sed 's/\t$/\t<empty>/g' >
file_tab-delim.txt
$
最后,让我们返回给我带来麻烦的字符串。我们可以得到如下所需的输出:
>
现在,相同的命令没有管道到$ cat > file_pipe-delim.txt<<EOF
> ||dolor|sit
> amet,||adipiscing|
> sed|do|eiusmod|tempor
> |||
> |aliqua.|Ut|
> EOF
$ awk '{$1=$1; n_empty=0; for(i=1; i<=NF; i++)
{if($i=="") {$i="<empty>"; n_empty++;}}; print;} END
{print n_empty" entries are empty" | "cat 1>&2";}'
FS='|' OFS=$'\t' file_pipe-delim.txt > file_tab-delim.txt
$ cat -A file_tab-delim.txt
<empty>^I<empty>^Idolor^Isit$
amet,^I<empty>^Iadipiscing^I<empty>$
sed^Ido^Ieiusmod^Itempor$
<empty>^I<empty>^I<empty>^I<empty>$
<empty>^Ialiqua.^IUt^I<empty>$
$
,这意味着我们不会看到每个$ echo "||lorem|ipsum||sit|amet,||||eiusmod|tempor|||labore|" | awk '{$1=$1; n_empty=0; for(i=1; i<=NF; i++) {if($i=="") {$i="<empty>"; n_empty++;}}; print;} END {print n_empty" entries are empty" | "cat 1>&2";}' FS='|' OFS=$'\t' | cat -A
<empty>^I<empty>^Ilorem^Iipsum^I<empty>^Isit^Iamet,^I<empty>^I<empty>^I<empty>^Ieiusmod^Itempor^I<empty>^I<empty>^Ilabore^I<empty>$
9 entries are empty
的{{1}};我们只会看到文本,因为它是“标签式”。
cat -A
答案 0 :(得分:2)
awk '
{
$1=$1;
for(i=1; i<NF; i++) {
if($i=="") { $i="<empty>"; empty++ }
};
print
}
END { print empty" empty" | "cat 1>&2"; }
' FS='|' OFS=$'\t'
应该做的伎俩。 $ 1 = $ 1告诉awk&#34;重建&#34;输入字段,以便它们可以与新的OutputFieldSeparator(OFS)一起使用。
print empty" empty" | "cat 1>&2"
打印&#34; n清空&#34;到斯特德尔。如果您愿意,可以省略它
答案 1 :(得分:1)
您只需要执行||
- &gt; |<empty>|
替换两次,无论该模式出现多少次,只要您每次都全局执行:
$ sed 's/||/|<empty>|/g; s/||/|<empty>|/g; s/|/\t/g' file
lorem ipsum <empty> sit amet, <empty> <empty> <empty> eiusmod tempor <empty> <empty> labore
或者如果您更喜欢awk:
$ awk '{while(gsub(/\|\|/,"|<empty>|")); gsub(/\|/,"\t")} 1' file
lorem ipsum <empty> sit amet, <empty> <empty> <empty> eiusmod tempor <empty> <empty> labore
对于某些seds,您可能需要'$'\t''
而不只是\t
。