我有一个csv文件,其中一些单元格里面有换行符。例如:
id,name
01,"this is
with newline"
02,no newline
我想删除单元格中的所有换行符。
如何使用正则表达式或其他终端工具一般不事先知道列数?
答案 0 :(得分:6)
这实际上是一个比它看起来更难的问题,在我看来,这意味着regex
不是正确的解决方案。因为您正在处理引用/转义字符串,跨越多个“行”,最终会导致复杂且难以阅读#!/usr/bin/env perl
use strict;
use warnings;
use Text::CSV;
my $csv = Text::CSV->new( { binary => 1, eol => "\n" } );
while ( my $row = $csv->getline( \*ARGV ) ) {
s/\n/ /g for @$row;
$csv->print( \*STDOUT, $row );
}
。 (这不是不可能的,它只是凌乱)。
我建议改为 - 使用解析器。 Perl在Text::CSV
中有一个,它有点像这样:
\*ARGV
这将在命令行中将文件作为管道输入/指定 - 这是sed
所做的 - 它是一个特殊的文件句柄,可以让你...基本上是somecommand.sh | myscript.pl
myscript.pl filename_to_process
所做的:
ARGV
自动\*STDIN
文件句柄。 (如果您愿意,可以明确打开文件或使用 <table class="table table-bordered" style="width: 80%;margin:5% 10%;background:slateblue">
<tr>
<th>#</th>
<th>item</th>
<th>item name</th>
<th>Added_at</th>
<tr>
<?php $i=1 ?>
@foreach($items as $item)
<tr>
<td><input type="checkbox" id="bought" name="{{$item->item_name}}" class="checkbox1"></td>
<td>{{$item->id}}</td>
<td>{{$item->item_name}}</td>
<td>{{$item->date}}
</tr>
@endforeach
</table>
<form class="shopped" method="post" action="{{url('post-data')}}" hidden><br>
{!! csrf_field()!!}
<h4 align="center">Add some information to mark as shopped</h4>
<label for ="item">Items</label>
<input type="text" class ="item" disabled><br>
<label for ="price">Price</label>
<input type="text" name="price"><br>
<label for ="store_name">Store</label>
<input type="text" name="store_name"><br>
<input type="submit" value="Add as purchased" class="btn btn-info" style="margin:20px 0 20px 60px"><br>
</form>
)
答案 1 :(得分:1)
如何使用正则表达式或其他终端工具一般不事先知道列数?
我认为正则表达式不是最合适的方法,最终可能会变得非常复杂。相反,我认为从长远来看,处理文件的单独程序可能更容易维护。
由于您可以使用任何终端工具,我选择了python,代码如下:
#!/usr/bin/python3 -B
import csv
import sys
with open(sys.argv[1]) as csvfile:
reader = csv.reader(csvfile)
for row in reader:
stripped = [col.replace('\n', ' ') for col in row]
print(','.join(stripped))
我认为上面的代码非常简单易懂,无需复杂的正则表达式。
此处的输入文件包含以下内容:
id,name
01,"this is
with newline"
02,no newline
为证明其有效,其输出如下:
➜ ~ ./test.py input.csv
id,name
01,this is with newline
02,no newline
您可以从其他程序调用python脚本并将文件名提供给它。你只需要为python程序添加一个小更新来写出文件,如果那是你真正需要的。
我已经用空格替换换行符以避免可能不需要的连接(例如this iswith newline
),但您可以用您想要的任何内容替换换行符,包括空字符串''
。
答案 2 :(得分:1)
我怀疑不是删除换行符,而是实际上想要用空格替换换行符。如果您的输入文件看起来很简单,那么应该为您完成:
$ awk '{ORS=( (c+=gsub(/"/,"&"))%2 ? FS : RS )} 1' file
id,name
01,"this is with newline"
02,no newline
答案 3 :(得分:0)
我写了一个方法来删除单元格中嵌入的新行。下面的方法返回一个java.util.List对象,该对象包含CSV文件中的所有行
List<String> getAllRowsInCSVFileAsList(File selectedCSVFile){
FileReader fileReader = null;
BufferedReader reader = null;
List<String> values = new ArrayList<String>();
try{
fileReader = new FileReader(selectedCSVFile);
reader = new BufferedReader(fileReader);
String line = reader.readLine();
String previousLine = "";
//
boolean intendLineInCell = false;
while(line != null){
if(intendLineInCell){
if(line.indexOf("\"") != -1 && line.indexOf("\"") == line.lastIndexOf("\"")){
previousLine += line;
values.add(previousLine);
previousLine = "";
intendLineInCell = false;
} else if(line.indexOf("\"") != -1 && line.indexOf("\"") != line.lastIndexOf("\"")){
if(getTotalNumberOfCharacterSequenceOccurrenceInString("\"", line) % 2 == 0){
previousLine += line;
}else{
previousLine += line;
values.add(previousLine);
previousLine = "";
intendLineInCell = false;
}
} else{
previousLine += line;
}
}else{
if(line.indexOf("\"") == -1){
values.add(line);
}else if ((line.indexOf("\"") == line.lastIndexOf("\"")) && line.indexOf("\"") != -1){
intendLineInCell = true;
previousLine = line;
}else if(line.indexOf("\"") != line.lastIndexOf("\"") && line.indexOf("\"") != -1){
values.add(line);
}
}
line = reader.readLine();
}
}catch(IOException ie){
ie.printStackTrace();
}finally{
if(fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return values;
}
int getTotalNumberOfCharacterSequenceOccurrenceInString(String characterSequence, String text){
int count = 0;
while(text.indexOf(characterSequence) != -1){
text = text.replaceFirst(characterSequence, "");
count++;
}
return count;
}
想象一下,您正在创建一个包含一行和五列的csv文件,在第四个单元格中,您有一个嵌入的新行(在单元格内输入)
您的数据将如下所示(实际上我们在csv中只有一行,但如果您在记事本中打开它,它将看起来像2行)。
dinesh,kumar,24,"23
tambaram india",green
如果单元格内部有输入,则可能如下所示
"23
tambaram india"
该单元格以双引号(&#34;)开头,以双引号结束(&#34;)。
如果有双引号(&#34;),在阅读该行的同时使用双引号(&#34;),我们可以理解单元格中有嵌入的输入。
代码用该行连接下一行并检查是否有结束双引号(&#34;)。如果有,它会在java.util.List对象中添加一个新行,否则它将连接下一行并检查它是否为结束双引号(&#34;),依此类推。这里我已经解释了一个单元格,但是如果行中有很多嵌入了enter的单元格,该方法也可以工作。
答案 4 :(得分:-2)
使用notepadd ++打开* csv文件,然后按Ctrl + H.转到选项卡替换并输入搜索框“换行”,然后写入以替换要替换的单词,或者如果需要,将其清空。