Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在管道分隔文件中的字段中查找并替换管道分隔符_Linux_Shell_Unix_Awk_Sed - Fatal编程技术网

Linux 在管道分隔文件中的字段中查找并替换管道分隔符

Linux 在管道分隔文件中的字段中查找并替换管道分隔符,linux,shell,unix,awk,sed,Linux,Shell,Unix,Awk,Sed,我之前有过类似的问题,后来我不得不给这个问题增加更多的范围,但不知道如何编辑它,使它再次生效。这就是为什么我要发布一个新问题 我的文件是以管道分隔的文件 NAME | NUM | WEB | LOCATION | CURRENCY | PLACE ABCD | 04 | GO|OGLE | EUROPE | EURO | PARIS XYZE | 12 | Y|A|HOO | USA | DOLLAR | SEATTLE LMNO | 17 | |FACE|B|O|O|K

我之前有过类似的问题,后来我不得不给这个问题增加更多的范围,但不知道如何编辑它,使它再次生效。这就是为什么我要发布一个新问题

我的文件是以管道分隔的文件

 NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
 ABCD | 04  | GO|OGLE | EUROPE | EURO   | PARIS
 XYZE | 12  | Y|A|HOO | USA    | DOLLAR | SEATTLE
 LMNO | 17  | |FACE|B|O|O|K | ASIA | ASIAN DOLLAR | HONGKONG
 EDDE | 98  | A||M|AZ|ON| | AFRICA | AF DOLLAR | CAPETOWN
我的文件和这一样复杂。我们需要从WEB字段中删除“|”符号,并将其替换为垃圾值,如#、$、或其他任何值

输出必须是:

NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
ABCD | 04  | GO#OGLE | EUROPE | EURO   | PARIS
XYZE | 12  | Y#A#HOO | USA    | DOLLAR | SEATTLE
LMNO | 17  | #FACE#B#O#O#K | ASIA | ASIAN DOLLAR | HONGKONG
EDDE | 98  | A##M#AZ#ON# | AFRICA | AF DOLLAR | CAPETOWN
NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
ABCD | 04  | GO#OGLE | EUROPE | EURO   | PARIS
XYZE | 12  | Y#A#HOO | USA    | DOLLAR | SEATTLE
LMNO | 17  | #FACE#B#O#O#K | ASIA | ASIAN DOLLAR | HONGKONG
EDDE | 98  | A##M#AZ#ON# | AFRICA | AF DOLLAR | CAPETOWN
我试着用一些过滤器来清理这个烂摊子。似乎没有什么能找到一个幸福的结局。非常感谢。
我要感谢回答我上一个问题的几个人:罗曼佩雷克赫斯特、埃德·莫顿、谢尔特、瓦尔·罗格

您可以使用此
awk
命令:

awk 'BEGIN{FS=OFS="|"} NR==1{n=NF} NF > n {
s=$3; for (i=4; i<=NF-3; i++) {s = s "#" $i; $i=""} $3=s; gsub(/\|{2,}/, "|")} 1' file

NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
ABCD | 04  | GO#OGLE | EUROPE | EURO   | PARIS
XYZE | 12  | Y#A#HOO | USA    | DOLLAR | SEATTLE
LMNO | 17  | #FACE#B#O#O#K | ASIA | ASIAN DOLLAR | HONGKONG
EDDE | 98  | A##M#AZ#ON# | AFRICA | AF DOLLAR | CAPETOWN
awk'BEGIN{FS=OFS=“|”}NR==1{n=NF}NF>n{

s=$3;对于(i=4;i您可以使用此
awk
命令:

awk 'BEGIN{FS=OFS="|"} NR==1{n=NF} NF > n {
s=$3; for (i=4; i<=NF-3; i++) {s = s "#" $i; $i=""} $3=s; gsub(/\|{2,}/, "|")} 1' file

NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
ABCD | 04  | GO#OGLE | EUROPE | EURO   | PARIS
XYZE | 12  | Y#A#HOO | USA    | DOLLAR | SEATTLE
LMNO | 17  | #FACE#B#O#O#K | ASIA | ASIAN DOLLAR | HONGKONG
EDDE | 98  | A##M#AZ#ON# | AFRICA | AF DOLLAR | CAPETOWN
awk'BEGIN{FS=OFS=“|”}NR==1{n=NF}NF>n{

s=$3;对于(i=4;i另一个
awk
解决方案可以是:-

awk  -F'[[:space:]][|][[:space:]]' '{gsub(/\|/,"#",$3);print $1,"|",$2,"|",$3,"|",$4,"|",$5,"|",$6}' file.txt
说明:-

-F - for field separator here it is space|space
gsub - global substitution in field 3. i.e. every occurance of | will be replaced by #. 
print - just print all the columns separated by "|"
输出将是:-


另一种
awk
解决方案可以是:-

awk  -F'[[:space:]][|][[:space:]]' '{gsub(/\|/,"#",$3);print $1,"|",$2,"|",$3,"|",$4,"|",$5,"|",$6}' file.txt
说明:-

-F - for field separator here it is space|space
gsub - global substitution in field 3. i.e. every occurance of | will be replaced by #. 
print - just print all the columns separated by "|"
输出将是:-

$cat tst.awk
开始{FS=OFS=“|”}
NR==1{outNf=NF;打印;下一个}
{
end=beg+(NF-outNf)-1
对于(i=1;i=beg&i
$cat tst.awk
开始{FS=OFS=“|”}
NR==1{outNf=NF;打印;下一个}
{
end=beg+(NF-outNf)-1

对于(i=1;i=beg&&i如果您不介意使用Perl

如果有空间,我们可以通过以下方式打印:

stackoverflow ❱ perl -F'\s+|\s+' -a -le  'print $F[5]' file
WEB
GO|OGLE
Y|A|HOO
|FACE|B|O|O|K
A||M|AZ|ON|
stackoverflow ❱  
由于我们可以在Perl中修改
@F
数组;因此我们可以:

$F[5] =~ s/\|/#/g;  
它只修改此列,不修改其他列

最终我们可以打印出来:

stackoverflow ❱ perl -F'\s+|\s+' -lae  '$F[5] =~ s/\|/#/g;print "@F"' file
 NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
 ABCD | 04 | GO#OGLE | EUROPE | EURO | PARIS
 XYZE | 12 | Y#A#HOO | USA | DOLLAR | SEATTLE
 LMNO | 17 | #FACE#B#O#O#K | ASIA | ASIAN DOLLAR | HONGKONG
 EDDE | 98 | A##M#AZ#ON# | AFRICA | AF DOLLAR | CAPETOWN
stackoverflow ❱  

如果您的文件没有空间,正如有人评论我的那样;那么您可以分散其他列;只修改该列并将它们全部连接在一起:

stackoverflow ❱ cat file2
NAME|NUM|WEB|LOCATION|CURRENCY|PLACE
ABCD|04|GO|OGLE|EUROPE|EURO|PARIS
XYZE|12|Y|A|HOO|USA|DOLLAR|SEATTLE
LMNO|17||FACE|B|O|O|K|ASIA|ASIANDOLLAR|HONGKONG
EDDE|98|A||M|AZ|ON||AFRICA|AFDOLLAR|CAPETOWN
stackoverflow ❱ perl -F'\|' -le  '$s=$#F;$e="@F[2..$s-3]";$e=~s/ +/#/g;print join "|", @F[0..1],$e,join "|",@F[$s-2,$s-1,$s]' file2
NAME|NUM|WEB|LOCATION|CURRENCY|PLACE
ABCD|04|GO#OGLE|EUROPE|EURO|PARIS
XYZE|12|Y#A#HOO|USA|DOLLAR|SEATTLE
LMNO|17|#FACE#B#O#O#K|ASIA|ASIANDOLLAR|HONGKONG
EDDE|98|A#M#AZ#ON#|AFRICA|AFDOLLAR|CAPETOWN

如果您不介意使用Perl

如果有空间,我们可以通过以下方式打印:

stackoverflow ❱ perl -F'\s+|\s+' -a -le  'print $F[5]' file
WEB
GO|OGLE
Y|A|HOO
|FACE|B|O|O|K
A||M|AZ|ON|
stackoverflow ❱  
由于我们可以在Perl中修改
@F
数组;因此我们可以:

$F[5] =~ s/\|/#/g;  
它只修改此列,不修改其他列

最终我们可以打印出来:

stackoverflow ❱ perl -F'\s+|\s+' -lae  '$F[5] =~ s/\|/#/g;print "@F"' file
 NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
 ABCD | 04 | GO#OGLE | EUROPE | EURO | PARIS
 XYZE | 12 | Y#A#HOO | USA | DOLLAR | SEATTLE
 LMNO | 17 | #FACE#B#O#O#K | ASIA | ASIAN DOLLAR | HONGKONG
 EDDE | 98 | A##M#AZ#ON# | AFRICA | AF DOLLAR | CAPETOWN
stackoverflow ❱  

如果您的文件没有空间,正如有人评论我的那样;那么您可以分散其他列;只修改该列并将它们全部连接在一起:

stackoverflow ❱ cat file2
NAME|NUM|WEB|LOCATION|CURRENCY|PLACE
ABCD|04|GO|OGLE|EUROPE|EURO|PARIS
XYZE|12|Y|A|HOO|USA|DOLLAR|SEATTLE
LMNO|17||FACE|B|O|O|K|ASIA|ASIANDOLLAR|HONGKONG
EDDE|98|A||M|AZ|ON||AFRICA|AFDOLLAR|CAPETOWN
stackoverflow ❱ perl -F'\|' -le  '$s=$#F;$e="@F[2..$s-3]";$e=~s/ +/#/g;print join "|", @F[0..1],$e,join "|",@F[$s-2,$s-1,$s]' file2
NAME|NUM|WEB|LOCATION|CURRENCY|PLACE
ABCD|04|GO#OGLE|EUROPE|EURO|PARIS
XYZE|12|Y#A#HOO|USA|DOLLAR|SEATTLE
LMNO|17|#FACE#B#O#O#K|ASIA|ASIANDOLLAR|HONGKONG
EDDE|98|A#M#AZ#ON#|AFRICA|AFDOLLAR|CAPETOWN

一个简单的awk解决方案:

awk  -F "|" '{printf $1} 
{for(i=2; i<=NF; i++) { if(i>3 && i<NF-2)printf "#"$i; else printf "|"$i } printf "\n"} ' file

NAME|NUM|WEB|LOCATION|CURRENCY|PLACE
ABCD|04|GO#OGLE|EUROPE|EURO|PARIS
XYZE|12|Y#A#HOO|USA|DOLLAR|SEATTLE
LMNO|17|#FACE#B#O#O#K|ASIA|ASIANDOLLAR|HONGKONG
EDDE|98|A##M#AZ#ON#|AFRICA|AFDOLLAR|CAPETOWN
awk-F“|”{printf$1}

{对于(i=2;i3&&i一个简单的awk解决方案:

awk  -F "|" '{printf $1} 
{for(i=2; i<=NF; i++) { if(i>3 && i<NF-2)printf "#"$i; else printf "|"$i } printf "\n"} ' file

NAME|NUM|WEB|LOCATION|CURRENCY|PLACE
ABCD|04|GO#OGLE|EUROPE|EURO|PARIS
XYZE|12|Y#A#HOO|USA|DOLLAR|SEATTLE
LMNO|17|#FACE#B#O#O#K|ASIA|ASIANDOLLAR|HONGKONG
EDDE|98|A##M#AZ#ON#|AFRICA|AFDOLLAR|CAPETOWN
awk-F“|”{printf$1}

{for(i=2;i3&&i我没有试着把它放在一行,而是让它更容易阅读。玩游戏的人可以大大减少它。这个想法是锚定前两个字段和后三个字段

#!/usr/bin/perl

while(<DATA>) {
  chomp;
  if(($name, $num, $web, $location, $currency, $place) = $_ =~
     /^([^\|]+)\|([^\|]+)\|(.+)\|([^\|]+)\|([^\|]+)\|([^\|]+)$/) {
    $web =~ tr/\|/\_/;
    printf "%s\n", join('|', ($name, $num, $web, $location, $currency, $place));
  }
}
__DATA__
 NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
 ABCD | 04  | GO|OGLE | EUROPE | EURO   | PARIS
 XYZE | 12  | Y|A|HOO | USA    | DOLLAR | SEATTLE
 LMNO | 17  | |FACE|B|O|O|K | ASIA | ASIAN DOLLAR | HONGKONG
 EDDE | 98  | A||M|AZ|ON| | AFRICA | AF DOLLAR | CAPETOWN

我没有试着把它放在一行,而是让它更容易阅读。那些玩游戏的人将能够大大减少它。这个想法是锚定前两个字段和最后三个字段

#!/usr/bin/perl

while(<DATA>) {
  chomp;
  if(($name, $num, $web, $location, $currency, $place) = $_ =~
     /^([^\|]+)\|([^\|]+)\|(.+)\|([^\|]+)\|([^\|]+)\|([^\|]+)$/) {
    $web =~ tr/\|/\_/;
    printf "%s\n", join('|', ($name, $num, $web, $location, $currency, $place));
  }
}
__DATA__
 NAME | NUM | WEB | LOCATION | CURRENCY | PLACE
 ABCD | 04  | GO|OGLE | EUROPE | EURO   | PARIS
 XYZE | 12  | Y|A|HOO | USA    | DOLLAR | SEATTLE
 LMNO | 17  | |FACE|B|O|O|K | ASIA | ASIAN DOLLAR | HONGKONG
 EDDE | 98  | A||M|AZ|ON| | AFRICA | AF DOLLAR | CAPETOWN


定界符后面总是跟空格吗?不,不是。它们都是紧密排列的。为了更好的说明,我这样写的。那么你怎么知道,在像
acbd | 02 | gh | ij | kl | mn | op | qr>这样的字符串上,web字段的开始和结束位置?最初的问题是我们确定第二个字段是“NUM”关于位置字段,即第四个字段,这在文件中不会改变。任何位于这两个字段之间的字段都必须仔细检查。分隔符是否始终后跟空格?不,不是。它们都是紧密排列的。为了更好地说明,我这样写的,那么你怎么知道,在一个字符串上,如
acbd | 02 | gh | ij | kl | mn | op | qr
web字段的开始和停止位置?最初的问题是我们确定第二个字段是“NUM”关于位置字段(第四个字段),这在文件中不会更改。任何位于这两个字段之间的字段都必须仔细检查。请注意,这个答案适用于给定的示例数据,只适用于转换第三个字段中的额外字段。嗨,Anubhav.“gsub(/\\\\{2,}/,“|”)是什么意思这里。你能简单介绍一下在gsub(/\\{2,}/,“|”)}中“2”的用法是什么,为什么在for循环中设置i=4。
i=4
因为我们从第四个字段开始抓取额外字段。
gsub
函数在
$i=”中将每个额外列设置为空后被调用“
并将额外的连续
替换为单个
注意,此答案适用于给定的样本数据,并且仅适用于转换第三个字段中的额外字段。嗨,阿努巴夫..这里的“gsub(/\\\\\{2,}/,“|”)是什么意思。你能简单介绍一下gsub(/\\\\\{2,}/,“|”)中的“2”是什么用法吗?”“为什么在for循环中设置i=4。
i=4
因为我们从第4个字段开始抓取额外字段。
gsub
函数在
$i=“”中将每个额外列设置为空后调用”
并用单个
@mac|u online替换额外的连续
:这是一个简单的通用解决方案。嗨,哇,这也是一个很好的解决方案。我可以知道为什么在for循环中为for循环设置i=2吗for循环中字段以这种方式打印[operator][value],即以operator“#”或“|”前缀的值。我在for循环之前打印了第一个字段,因为它不需要前缀,然后使用for循环从第二个字段到最后一个字段来实现我们所需的逻辑。@mac_online:这可以使用空格/不使用空格。这是一个简单的通用解决方案。嗨,哇,这也是一个很好的解决方案。我可以知道为什么在for循环中为for循环设置I=2吗是时尚[operator][value],即以运算符“#”或“|”作为前缀的值。我在for循环之前打印了第一个字段,因为它不需要前缀,然后使用for循环从第二个字段到最后一个字段来实现我们想要的逻辑。我不是100%确定,但我认为这就是@k-five所做的。职业高尔夫球手!我不是100%确定,但我认为这就是@k-five所做的。职业高尔夫球手!到目前为止